sin

Building a Dictaphone Using Media Recorder and getUserMedia

Chris Mills brushes up his shorthand and shows how the MediaStream Recording API in modern browsers can be used to capture audio directly from the user’s device. Inching ever closer to the capabilities of native software, it truly is an exciting time to be a web developer.


The MediaStream Recording API makes it easy to record audio and/or video streams. When used with MediaDevices.getUserMedia(), it provides an easy way to record media from the user’s input devices and instantly use the result in web apps. This article shows how to use these technologies to create a fun dictaphone app.

A sample application: Web Dictaphone

To demonstrate basic usage of the MediaRecorder API, we have built a web-based dictaphone. It allows you to record snippets of audio and then play them back. It even gives you a visualisation of your device’s sound input, using the Web Audio API. We’ll just concentrate on the recording and playback functionality in this article, for brevity’s sake.

You can see this demo running live, or grab the source code on GitHub. This has pretty good support on modern desktop browsers, but pretty patchy support on mobile browsers currently.

Basic app setup

To grab the media stream we want to capture, we use getUserMedia(). We then use the MediaRecorder API to record the stream, and output each recorded snippet into the source of a generated <audio> element so it can be played back.

We’ll first declare some variables for the record and stop buttons, and the <article> that will contain the generated audio players:

const record = document.querySelector('.record');
const stop = document.querySelector('.stop');
const soundClips = document.querySelector('.sound-clips');

Next, we set up the basic getUserMedia structure:

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
   console.log('getUserMedia supported.');
   navigator.mediaDevices.getUserMedia (
      // constraints - only audio needed for this app
      {
         audio: true
      })

      // Success callback
      .then(function(stream) {

      })

      // Error callback
      .catch(function(err) {
         console.log('The following `getUserMedia` error occured: ' + err);
      }
   );
} else {
   console.log('getUserMedia not supported on your browser!');
}

The whole thing is wrapped in a test that checks whether getUserMedia is supported before running anything else. Next, we call getUserMedia() and inside it define:

  • The constraints: Only audio is to be captured for our dictaphone.
  • The success callback: This code is run once the getUserMedia call has been completed successfully.
  • The error/failure callback: The code is run if the getUserMedia call fails for whatever reason.

Note: All of the code below is found inside the getUserMedia success callback in the finished version.

Capturing the media stream

Once getUserMedia has created a media stream successfully, you create a new Media Recorder instance with the MediaRecorder() constructor and pass it the stream directly. This is your entry point into using the MediaRecorder API — the stream is now ready to be captured into a <Blob>, in the default encoding format of your browser.

const mediaRecorder = new MediaRecorder(stream);

There are a series of methods available in the MediaRecorder interface that allow you to control recording of the media stream; in Web Dictaphone we just make use of two, and listen to some events. First of all, MediaRecorder.start() is used to start recording the stream once the record button is pressed:

record.onclick = function() {
  mediaRecorder.start();
  console.log(mediaRecorder.state);
  console.log("recorder started");
  record.style.background = "red";
  record.style.color = "black";
}

When the MediaRecorder is recording, the MediaRecorder.state property will return a value of “recording”.

As recording progresses, we need to collect the audio data. We register an event handler to do this using mediaRecorder.ondataavailable:

let chunks = [];

mediaRecorder.ondataavailable = function(e) {
  chunks.push(e.data);
}

Last, we use the MediaRecorder.stop() method to stop the recording when the stop button is pressed, and finalize the Blob ready for use somewhere else in our application.

stop.onclick = function() {
  mediaRecorder.stop();
  console.log(mediaRecorder.state);
  console.log("recorder stopped");
  record.style.background = "";
  record.style.color = "";
}

Note that the recording may also stop naturally if the media stream ends (e.g. if you were grabbing a song track and the track ended, or the user stopped sharing their microphone).

Grabbing and using the blob

When recording has stopped, the state property returns a value of “inactive”, and a stop event is fired. We register an event handler for this using mediaRecorder.onstop, and construct our blob there from all the chunks we have received:

mediaRecorder.onstop = function(e) {
  console.log("recorder stopped");

  const clipName = prompt('Enter a name for your sound clip');

  const clipContainer = document.createElement('article');
  const clipLabel = document.createElement('p');
  const audio = document.createElement('audio');
  const deleteButton = document.createElement('button');

  clipContainer.classList.add('clip');
  audio.setAttribute('controls', '');
  deleteButton.innerHTML = "Delete";
  clipLabel.innerHTML = clipName;

  clipContainer.appendChild(audio);
  clipContainer.appendChild(clipLabel);
  clipContainer.appendChild(deleteButton);
  soundClips.appendChild(clipContainer);

  const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  chunks = [];
  const audioURL = window.URL.createObjectURL(blob);
  audio.src = audioURL;

  deleteButton.onclick = function(e) {
    let evtTgt = e.target;
    evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
  }
}

Let’s go through the above code and look at what’s happening.

First, we display a prompt asking the user to name their clip.

Next, we create an HTML structure like the following, inserting it into our clip container, which is an <article> element.

<article class="clip">
  <audio controls></audio>
  <p>_your clip name_</p>
  <button>Delete</button>
</article>

After that, we create a combined Blob out of the recorded audio chunks, and create an object URL pointing to it, using window.URL.createObjectURL(blob). We then set the value of the <audio> element’s src attribute to the object URL, so that when the play button is pressed on the audio player, it will play the Blob.

Finally, we set an onclick handler on the delete button to be a function that deletes the whole clip HTML structure.

So that’s basically it — we have a rough and ready dictaphone. Have fun recording those Christmas jingles! As a reminder, you can find the source code, and see it running live, on the MDN GitHub.


This article is based on Using the MediaStream Recording API by Mozilla Contributors, and is licensed under CC-BY-SA 2.5.


About the author

Chris Mills manages the MDN web docs writers’ team at Mozilla, which involves spreadsheets, meetings, writing docs and demos about open web technologies, and occasional tech talks at conferences and universities. He used to work for Opera and W3C, and enjoys playing heavy metal drums and drinking good beer.

More articles by Chris




sin

Suburban Xanadu [electronic resource] : the Casino Resort on the Las Vegas Strip and Beyond

Hoboken : Taylor & Francis, 2003.




sin

The moccasin game [electronic resource] / produced by the National Film Board of Canada. --

Montreal : National Film Board of Canada, 1983.




sin

MITCHELL, GERALD P. v. WISCONSIN. Decided 06/27/2019




sin

Reflections on socialism in the Twenty-First Century: facing market liberalism, rising inequalities and the environmental imperative / Claes Brundenius, editor

Online Resource




sin

The light that failed: why the West is losing the fight for democracy / Ivan Krastev and Stephen Holmes

Dewey Library - JC574.K74 2019




sin

The Putin system: an opposing view / Grigory Yavlinsky

Dewey Library - JN6695.I36813 2019




sin

Electronic warfare signal processing / James Genova

Barker Library - UG485.G46 2018




sin

Disarming Doomsday: the human impact of nuclear weapons since Hiroshima / Becky Alexis-Martin

Dewey Library - U263.A44 2019




sin

Shopian killings: Separatist leader Yasin Malik along with other JKLF leaders detained

Leaders were going to Shopian with relief material, including foodgrains and medicines.




sin

Dilsukhnagar blasts case: Yasin Bhatkal brought to Hyderabad

Yaskin Bhatkal's close associate Asadullah Akhtar is presently being interrogated by the NIA.




sin

Ishrat Jahan case: CBI questions Gujarat Law Minister Bhupendrasinh Chudasama

CBI said Chudasama was allegedly present during the meeting held for protecting police personnel.




sin

Navjot Singh Sidhu to begin fast-unto-death from Saturday

"My duty towards Amritsar would never be stopped"




sin

Rahul Gandhi should apologise for his remarks on ordinance: Shivraj Singh Chouhan

"By making such a statement, Rahul has lowered the country's image"




sin

Small-time actress held for threatening and abusing cops

Anjum Nayar was arrested and booked under IPC sections 294, 504 and 506.




sin

Aarushi murder case: Talwars using dilatory tactics, says SC rejecting their plea

Aarushi was found dead with her throat slit in her bedroom on May 16, 2008.




sin

Ajit Singh's RLD to move SC for CBI probe into Muzaffarnagar violence

Singh hinted that the riots were orchestrated by ruling SP in collusion with BJP.




sin

JandK Assembly to summon V K Singh on payoff charge

Speaker Mubarak Gul said he would write to Singh and ask him to explain his allegations.




sin

Politics on any tragedy is unwanted: Shivraj Singh Chouhan

Earlier, Digvijay Singh had blamed corruption in plum postings for occurrence of such tragedies.




sin

SC orders V K Singh to explain 'serious statements', begins hearing contempt case

The apex court has pulled up ex-Army chief V K Singh for his comments on its verdict.




sin

Defence Ministry rejects Gen VK Singh's plea on secret unit

Plea rejected by Defence Ministry citing Section 8 (1) (a) of the Right to Information Act.




sin

Court issues production warrants against BSP MP Dhananjay Singh, wife Jagriti

MP was arrested for allegedly destroying evidence and not informing police about the maid's death.




sin

Punjab police "picks up" fasting Gurbaksh Singh; volunteer "replaces" him

Gurbaksh Singh is believed to be "continuing" with his hunger strike in jail.




sin

Muzaffarnagar riots: Politicians missing, officials in denial over relief camp deaths

Report by Shamli district administration claims 'zero'' child deaths while angry parents mourn.




sin

Rajnath Singh to inaugurate Nitin Gadkari's 'Agrovision'

Pawar had announced the idea of holding the expo in January this year.




sin

Computer algebra in scientific computing [electronic resource] : 9th international workshop, CASC 2006, Chişinău, Moldova, September 11-15, 2006 ; proceedings / Victor G. Ganzha, Ernst W. Mayr, Evgenii V. Vorozhtsov (eds.)

Berlin ; New York : Springer, 2006




sin

Computing in algebraic geometry [electronic resource] : a quick start using SINGULAR / Wolfram Decker, Christoph Lossen

Berlin ; Springer ; [2006]




sin

Computing the continuous discretely [electronic resource] : integer-point enumeration in polyhedra / Matthias Beck, Sinai Robins

New York : Springer, [2007]




sin

Dynamical systems with applications using mathematica [electronic resource] / Stephen Lynch

Boston, Mass. : Birkhäuser ; [2007]




sin

Das sintflutprinzip [electronic resource] : ein mathematik-roman / Gunter Dueck ; mit Illustrationen von Stefan Budian

Berlin ; New York : Springer, [2006]




sin

Managing natural resources : organizational strategy, behaviour and dynamics / edited by Gerard George (Dean & Lee Kong Chian Chair Professor of Innovation and Entrepreneurship, Lee Kong Chian School of Business, Singapore Management University, Singa




sin

Complex ecology : foundational perspectives on dynamic approaches to ecology and conservation / edited by Charles G. Curtin (University of Montana), Timothy F.H. Allen (University of Wisconsin, Madison)




sin

Microgrids and other local area power and energy systems / Alexis Kwasinski (University of Pittsburgh), Wayne Weaver (Michigan Technological University), Robert S. Balog (Texas A&M University)

Kwasinski, Alexis, 1970- author




sin

Satellite remote sensing for conservation action : case studies from aquatic and terrestrial ecosystems / edited by Allison K. Leidner (ASRC Federal/National Aeronautics and Space Administration), Graeme M. Buchanan (RSPB, Edinburgh, UK)




sin

Current and future impacts of climate change on housing, buildings and infrastructure / The Senate, Environment and Communications References Committee

Australia. Parliament. Senate. Environment and Communications References Committee




sin

Around the world in 80 species : exploring the business of extinction / edited by Jill Atkins and Barry Atkins




sin

In search of good energy policy / edited by Marc Ozawa (Cambridge University Energy Policy Research Group), Jonathan Chaplin (Cambridge University Faculty of Divinity), Michael Pollitt (Cambridge University Judge Business School), David Reiner (Cambridge




sin

Murray-Darling Basin Commission of Inquiry Bill 2019 / Environment and Communications Legislation Committee

Australia. Parliament. Senate. Environment and Communications Legislation Committee, author, issuing body




sin

Microsoft revenue beats estimates as Covid-19 crisis boosts cloud business

Microsoft benefited from strong demand for its Teams collaboration software, which now has 75 million users




sin

Apple to pay $18 mn to settle suit accusing it of breaking FaceTime: Report

Over 3.6 million devices are said to have been affected by the iOS 6 update and each class member will receive an estimated $3




sin

Apple, Google ban GPS tracking in apps using contract tracing framework

Both companies said privacy and preventing governments from using the system to compile data on citizens was a primary goal




sin

Animal Crossing boosts Nintendo's Switch console demand in Jan-Mar quarter

The Kyoto-based gaming company posted operating profit of 89.4 billion yen for January-March




sin

Singur Redux: Co pulls out of Haldia




sin

Film release stalled for ridiculing Mamata Banerjee,Tatas’ Singur exit




sin

Rape accused works for Varun Gandhi’s puja during Singur visit



  • DO NOT USE West Bengal
  • India

sin

West Bengal to benefit from NIA probe, says BJP state President Rahul Sinha



  • DO NOT USE West Bengal
  • India

sin

TMC can’t prevent BJP progress by terror: Rahul Sinha



  • DO NOT USE West Bengal
  • India

sin

Media houses criticising us to please Delhi: Mamata Banerjee



  • DO NOT USE West Bengal
  • India

sin

Mamata snaps back at media when asked about businessman’s detention



  • DO NOT USE West Bengal
  • India

sin

38 killed, 23 missing as landslides rock Darjeeling



  • DO NOT USE West Bengal
  • India