Recording to an Audio File using HTML5 and JS

Recording to an Audio File using HTML5 and JS

English: Screenshot of WAV file ripped from 20...
English: Screenshot of WAV file ripped from 2005 remaster (for Loudness War page) (Photo credit: Wikipedia)

Pure Native HTML5 Audio Recording is here and has been for a while, no more flash needed! Don’t get too excited though, it still requires a bit of work to support it in a consistent manner.

This post will focus on getting the recorded audio into the same file format across browsers. And yes, I spent a long time debugging in the browser!

Example

Here is the “simplest” way to record, play and download audio in Chrome (this also works in Firefox but ogg format is used instead of webm).

Optional: Use polyfill from WebRTC project to do some cross-browser support of the navigator.mediaDevices.getUserMedia function on older Firefox and Chrome browsers.

// appends an audio element to playback and download recording
function createAudioElement(blobUrl) {
const downloadEl = document.createElement(‘a’);
downloadEl.style = ‘display: block’;
downloadEl.innerHTML = ‘download’;
downloadEl.download = ‘audio.webm’;
downloadEl.href = blobUrl;
const audioEl = document.createElement(‘audio’);
audioEl.controls = true;
const sourceEl = document.createElement(‘source’);
sourceEl.src = blobUrl;
sourceEl.type = ‘audio/webm’;
audioEl.appendChild(sourceEl);
document.body.appendChild(audioEl);
document.body.appendChild(downloadEl);
}

// request permission to access audio stream
navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
// store streaming data chunks in array
const chunks = [];
// create media recorder instance to initialize recording
const recorder = new MediaRecorder(stream);
// function to be called when data is received
recorder.ondataavailable = e => {
// add stream data to chunks
chunks.push(e.data);
// if recorder is ‘inactive’ then recording has finished
if (recorder.state == ‘inactive’) {
// convert stream data chunks to a ‘webm’ audio format as a blob
const blob = new Blob(chunks, { type: ‘audio/webm’ });
// convert blob to URL so it can be assigned to a audio src attribute
createAudioElement(URL.createObjectURL(blob));
}
};
// start recording with 1 second time between receiving ‘ondataavailable’ events
recorder.start(1000);
// setTimeout to stop recording after 5 seconds
setTimeout(() => {
// this will trigger one final ‘ondataavailable’ event and set recorder state to ‘inactive’
recorder.stop();
}, 5000);
}).catch(console.error);

Native Support

Support for MediaRecorder is still not on Safari, IE or Edge. Chrome and Firefox also have different audio recording formats but the same codec. At time of writing these are the only supported native audio recording formats.

Browser Format Codec Mime Type
Chrome webm opus “audio/webm;codecs=opus”
Firefox ogg opus “audio/ogg;codecs=opus”

You can test the supported recording formats in the browser by using the MediaRecorder function isTypeSupported.

// true on chrome, false on firefox
MediaRecorder.isTypeSupported('audio/webm;codecs=opus')
// false on chrome, true on firefox
MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')

Remember: MediaRecorder !== MediaSource. Playing formats are much better supported than recording formats. See this excellent support media formats page.

The Format Problem

Recording audio in different formats across browsers is annoying, especially if you want the audio files sent to a backend.

Converting to a consistent audio format on the frontend before sending to the backend is a good solution. This is how Facebook Messenger and WhatsApp do their voice recording on the web.

They use a WebWorker on the client for the possible heavy audio conversion process before sending it to the backend.

The project web-audio-recorder-js also has some great examples of how to encode to WAV, OGG and MP3 in the browser. Including a demonstration of how to do the encoding in a WebWorker.

#1 Facebook Solution

Facebook messenger records the audio streaming data as before but then converts it in a WebWorker to a WAV format. They then send that format to the backend.

They do something very similar to this project I found by a Googler who seems to specialise in Web Audio.

POST request made to https://upload.facebook.com/ajax/mercury/upload.php with this payload which includes the “audio/wav” format.

#2 WhatsApp Solution

WhatsApp on Web convert the recorded data to an OGG format from inside a WebWorker. They use a library similar to opus.js-sample to do it – this means both Chrome, Firefox and other browsers can then use ogg.

They also access the microphone raw data similary to this article by Google developers. This uses the AudioContext API which is part of the Web Audio API, this means they can also add effects and filters before creating the output. I noticed they added a Butterworth Filter which I believe reduces background noise from the recording.

Interestingly they don’t also use navigator.mediaDevices.getUserMedia like Facebook do – they use navigator.getUserMedia which is a an older deprecated API but it checks out.

S Object before the POST request is sent, it contains the “audio/ogg; codecs=opus” mimeType.
alt

POST request is then made to https://mmi664.whatsapp.net.

alt

#3 Convert to MP3 Solution

Use a JS port of Lame like LameJS or libmp3lame-js to do the conversion to MP3 inside a WebWorker. Once converted, send the MP3 audio to the backend.

Here is a good explanation of how its possible to convert recorded audio to MP3.

#4 Backend Solution

Another alternative solution would be convert those ogg and webm formats to a consistent format after receiving them in the backend. Avoiding any kind of client-side work to convert them.

FFmpeg for example can do the conversion quite easily.

ffmpeg -i input.webm output.m4a  
ffmpeg -i input.ogg output.m4a  

Issues

Recording in Chrome produces a webm file without any meta data about the duration of the recording. This means when Chrome plays back the recording it has no idea how long it is! Ogg format on Firefox does not suffer from this.

There is a bug in Chromium open for this issue.

Conclusion

Recording Audio in the browser with the new HTML5 API is really nice. The downside is that the API is not yet supported in all browsers and recording formats are not consistent. There are solutions that can be used for both frontend and backend to tackle the problem though.

Happy recording!

Original Article -> https://air.ghost.io

12 Comments

  1. Thank you a lot for giving everyone remarkably terrific opportunity to read from this web site. It’s always so pleasing and also jam-packed with a great time for me personally and my office acquaintances to search your site at minimum three times every week to see the fresh things you have got. Of course, I’m also always fulfilled with the incredible suggestions you give. Some 3 tips in this article are in reality the most impressive we have all had.

  2. I together with my pals were actually viewing the nice ideas located on your web blog and then I got a terrible feeling I had not thanked the site owner for those techniques. All of the young men ended up totally passionate to see all of them and already have honestly been loving those things. I appreciate you for turning out to be quite thoughtful and also for considering such good guides millions of individuals are really eager to discover. Our honest apologies for not expressing gratitude to you sooner.

  3. I intended to put you one very little observation to thank you very much yet again for these extraordinary solutions you have contributed on this site. It is certainly tremendously open-handed with you to present publicly what a lot of people could possibly have offered for an e book to help make some cash on their own, primarily seeing that you could possibly have done it if you ever desired. These tricks also served to become a great way to be certain that other people online have similar dreams just as my own to see way more in regard to this problem. I’m certain there are a lot more pleasant periods ahead for individuals who examine your blog post.

  4. I wanted to type a small remark in order to say thanks to you for these amazing advice you are showing on this site. My rather long internet look up has at the end of the day been compensated with really good know-how to exchange with my companions. I ‘d suppose that most of us readers are undoubtedly endowed to exist in a fantastic website with very many brilliant professionals with useful pointers. I feel really fortunate to have seen the web page and look forward to really more cool times reading here. Thanks again for all the details.

  5. Thanks a lot for giving everyone an exceptionally marvellous possiblity to check tips from this web site. It’s always so nice and also stuffed with a great time for me personally and my office peers to visit the blog at minimum 3 times in 7 days to read the fresh issues you have got. And definitely, I’m at all times contented with the exceptional suggestions you serve. Some 1 points in this post are certainly the most suitable we have had.

  6. I and also my friends appeared to be looking through the best solutions from your web site and then the sudden developed a terrible feeling I never thanked the web blog owner for them. My boys are already as a consequence warmed to study them and have undoubtedly been enjoying those things. Appreciation for indeed being really thoughtful as well as for obtaining variety of essential issues most people are really eager to learn about. Our own honest apologies for not saying thanks to you sooner.

  7. I truly wanted to write down a simple word so as to appreciate you for the wonderful facts you are sharing at this site. My prolonged internet look up has finally been recognized with reasonable concept to exchange with my family. I would say that most of us readers actually are quite blessed to live in a fantastic network with many marvellous people with insightful techniques. I feel rather fortunate to have come across the web page and look forward to many more excellent minutes reading here. Thanks a lot once again for a lot of things.

  8. Thank you a lot for giving everyone such a special possiblity to read articles and blog posts from this web site. It really is so terrific and also packed with a great time for me and my office co-workers to visit the blog at least thrice in one week to see the fresh secrets you have. Not to mention, I’m just at all times astounded with the brilliant guidelines you give. Some 2 tips on this page are clearly the most impressive we have ever had.

  9. I truly wanted to send a brief note to be able to say thanks to you for these lovely solutions you are posting on this website. My long internet look up has now been rewarded with brilliant ideas to go over with my companions. I would say that many of us website visitors are really lucky to dwell in a great place with so many special people with helpful concepts. I feel rather privileged to have seen the website page and look forward to plenty of more awesome minutes reading here. Thanks again for a lot of things.

Leave a Reply

Your email address will not be published. Required fields are marked *