Record Audio in Tone.js with Tone.Recorder

This article explains how to use Tone.Recorder in Tone.js to capture and export audio directly from your web applications. You will learn what the recorder utility is, how to connect it to your audio sources, and the precise steps and code needed to start and stop a recording session to generate a downloadable audio file.

What is Tone.Recorder?

Tone.Recorder is a specialized utility class in the Tone.js library that acts as a bridge to the browser’s native MediaRecorder API. It allows developers to capture the audio output of any Tone.js node—such as a synthesizer, an effects chain, or the entire main output (Tone.Destination)—and encode it into an audio format, typically a WebM or WAV file.

Setting Up Tone.Recorder

To record audio, you must first instantiate the recorder and connect the audio source you want to capture to it.

// 1. Create the recorder instance
const recorder = new Tone.Recorder();

// 2. Create an audio source (e.g., a synthesizer)
const synth = new Tone.Synth().toDestination();

// 3. Connect the audio source to the recorder
synth.connect(recorder);

If you want to record the entire output of your application instead of just a single instrument, connect the main output destination to the recorder:

Tone.Destination.connect(recorder);

How to Start Recording

Starting a recording session is an asynchronous operation. You trigger it by calling the .start() method on your recorder instance.

// Start the recording session
await recorder.start();

Once .start() is called, any audio processed through the connected node will be written to the recorder’s buffer.

How to Stop Recording and Retrieve the Audio

To end the recording session, call the .stop() method. This method is also asynchronous and returns a promise that resolves to a Blob containing the recorded audio data.

// Stop the recording and retrieve the audio Blob
const recording = await recorder.stop();

Saving or Playing the Recorded Audio

Once you have the Blob, you can create a local URL to either play the audio back in an HTML <audio> element or download it to the user’s device.

Here is a complete, practical implementation:

const recorder = new Tone.Recorder();
const synth = new Tone.Synth().toDestination();
synth.connect(recorder);

// Start recording
async function startSession() {
  await Tone.start(); // Ensure the audio context is active
  recorder.start();
  console.log("Recording started...");
}

// Stop recording and download the file
async function stopSession() {
  const recordingBlob = await recorder.stop();
  
  // Create a download link for the audio file
  const url = URL.createObjectURL(recordingBlob);
  const anchor = document.createElement("a");
  anchor.download = "tonejs-recording.webm";
  anchor.href = url;
  anchor.click();
  
  console.log("Recording stopped and download triggered.");
}