Record audio without relying on Mediarecorder

I am combining two AudioBuffers to form a single one.
I believe this can be done without using the MediaRecorder, as real-time recording is not required.

This is my current approach:

concatenateAudio(buffers: AudioBuffer[]): void {
    const totalLength = buffers.reduce((acc, buffer) => acc + buffer.length, 0);
    const audioContext = new AudioContext();
    const audioBuffer = audioContext.createBuffer(1, totalLength, 48000);
    const source = audioContext.createBufferSource();
    const destination = audioContext.createMediaStreamDestination();

    let offset = 0;
    buffers.map((buffer) => {
        audioBuffer.getChannelData(0).set(buffer.getChannelData(0), offset);
        offset += buffer.length;
    });

    source.buffer = audioBuffer;
    source.connect(destination);
    source.start();

    this.saveRecordedAudio(destination.stream, audioBuffer.duration);
}

In the saveRecordedAudio() function, I pass the stream to a MediaRecorder.

The time taken to record the new stream is equivalent to the duration of playing the two AudioBuffers sequentially...
Is there an alternative method for accomplishing this?

Appreciate any suggestions. Thank you.

Answer №1

If you're feeling adventurous, there's a unique method to capture buffers simultaneously and link them up like pieces of a puzzle. By dividing the audio buffer into various chunks within the minimum chunk length limit, it is possible to execute this process in Chrome but not in FF.

However, caution must be exercised when employing this technique under any circumstances. (Taken from gist).

// attempting to split buffer to N parts, record concurrently, and generate blob
async function recordParallel() {
  const audioContext = new AudioContext();

  const bufs = [], all = []
  for (let i = 0; i < 10; i++ ) {
    // 2705 - min chunk length for opus encoder in Chrome, so we increase block size to 4096 plus silent header
    let buf = new AudioBuffer({length: 4096, sampleRate: audioContext.sampleRate})
    bufs.push(buf)
    let data = buf.getChannelData(0)
    for (let j = 0; j < 4096; j++) data[j] = Math.sin(j / ((i + 1) * 2))

    // create recorders
    const source = audioContext.createBufferSource();
    source.buffer = buf;

    const chunks = []
    all.push(new Promise(r => {
      const dest = audioContext.createMediaStreamDestination();
      const recorder = new MediaRecorder(dest.stream);
      source.connect(dest)

      recorder.start(10)
      // delay is needed to shift encodingblocks
      source.start(0)

      recorder.ondataavailable = (e) => {
        const blob = e.data
        if (blob.size) chunks.push(blob)
      }
      recorder.onstop = e => {
        r(chunks)
      }
      source.onended = e => {
        recorder.stop()
      }
    }))
  }

  const blobs = await Promise.all(all);

  // combine multiple recorders back
  console.log(blobs)
  var blob = new Blob([...blobs[0], ...blobs.slice(1).map(b => b.slice(1)).flat()], { 'type' : 'audio/ogg; codecs=opus' });
  let audio = document.createElement('audio')
  audio.src = URL.createObjectURL(blob);
  audio.play()
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transform the Node.js requests for both GET and POST methods to utilize Ajax

I am new to JavaScript and am currently learning how to send requests from a Node.js backend using Ajax for GET/POST operations. My backend is connected to a MySQL database and I have been studying some tutorials to gain a better understanding. Here is an ...

Access numerical values from JSON objects using JavaScript

I need assistance with implementing a JavaScript function to retrieve data from a JSON file and then display it on my webpage. The goal is to iterate through the values in a while loop and dynamically insert them into specific HTML elements. xhttp.onrea ...

Encountering a hiccup while trying to install Svelte, Skeleton, and Tail

Recently entering the world of Svelte and TypeScript, I have encountered some unexpected errors after installation. Despite following the same steps as before, I am puzzled by what is causing these issues. This is the process I followed: npm create svelte ...

The compiler error TS2304 is indicating that it cannot locate the declaration for the term 'OnInit'

I successfully completed the Angular superhero tutorial and everything was functioning properly. However, when I close the CMD window running NPM and then reopen a new CMD window to reissue the NPM START command, I encounter two errors: src/app/DashBoard ...

Vue in d3 - the property ownerDocument is not defined

I'm currently working on integrating d3 charts with Vue. I've noticed that using a ref seems to trigger an error, but is that the correct approach? <template> <div ref="chart"></div> </template> const char ...

When attempting to use $.ajax to send JSON, it instead sends a query string

I'm having an issue where I'm using ajax to send JSON data with the following script: var sendData = {"test":"opa"}; console.log(sendData); $.ajax({ contentType: "application/json", method: "POST", url: "/test", dataType: "json", ...

Failed Axios POST request on iOS devices

Attempting a straightforward ajax POST from domain1 to domain2 using Axios. This involves a cross-domain simple POST without requiring a PREFLIGHT (OPTIONS) call. The response returned by the application is a basic JSON string. This process functions smoo ...

Customizing the Class of a jQuery UI ui-autocomplete Combobox Container

Is there a way to customize the ui-autocomplete div by adding a custom class? I have several autocomplete widgets on my webpage, and I need to style their drop-downs differently. Since editing the ui-autocomplete class directly is not an option, I am wor ...

Continuously performing a task in Node.js every 2 minutes until a JSON file, which is being monitored for changes every few seconds

In order to modify a process while my program is running, I need to manually change a value in a .json object from 0 to 1. Now, I want the program to: periodically check the .json file for changes. refresh a browser page (using puppeteer) every 2 minutes ...

React-select fails to trigger form submission when the Enter key is pressed

Currently, I am utilizing Formik and React-Select in my project, and I'm hoping to enable the form submission by pressing enter while focused on a select input. Interestingly, when I'm focused on any other input field and press Enter, the form s ...

Error in AJAX transmission

I am encountering an unusual issue with the jQuery ajax function in my script. The problem is specific to my friend's computer, as I am not experiencing any difficulties on my own computer. While attempting to utilize the error function property to ...

What could be causing the variable to be undefined in the template?

I encountered an error message 121| <div class="container-fluid bg-dark text-white" style="margin-top: 2%;"> 122| >> 123| <h1 class="mb-1 text-center"><%= article.title %> < ...

Tips for navigating through the search results on Google Maps with Selenium

I am facing an issue where I am only able to retrieve the first 7 results out of 20 using the given code. It seems that I am unable to scroll to the bottom to access all the results. Can someone please advise on additional steps required to achieve the d ...

The value of req.session.returnTo is not defined

I have implemented passport for user authentication using discord oauth2. I want the users to be redirected back to the original page they came from instead of being directed to the home page or a dashboard. Even though I tried saving the URL in the sessi ...

Navigating through the world of WebSQL data entry

I've encountered a challenge while utilizing WebSQL for my Chrome Extension. This is my first experience with it, so I decided to refer to this tutorial and modify it to suit my requirements: http://www.html5rocks.com/en/tutorials/webdatabase/todo/ B ...

Ensure that the form is submitted only after confirming it in the modal with react-hook-form

**I am facing an issue with submitting react-hook-form on confirm in a modal component. Whenever the user selects confirm, I need the form to be submitted directly. I have tried writing the modal inside FormSubmitButton. Also, I have tried placing it insi ...

"Encountering an error stating 'SyntaxError: Unable to use import statement outside of a module' when attempting to import a module that itself imports another module for side

I'm currently working on writing Jest tests for my TypeScript code. To ensure compatibility with older browsers, I have included some polyfills and other necessary imports for side effects. Here is a snippet of my code (variables changed for anonymit ...

Why is the return type for the always true conditional not passing the type check in this scenario?

Upon examination, type B = { foo: string; bar: number; }; function get<F extends B, K extends keyof B>(f: F, k: K): F[K] { return f[k]; } It seems like a similar concept is expressed in a different way in the following code snippet: functi ...

Save information on the server and organize it into an array for use in local operations

Currently, I am working on the ShoppingApp using Angular for the front-end and Firebase for the backend. I have defined a model for the category as follows: import { ProductModel } from "./product.model"; export class CategoryModel { public id: number; ...

Using NodeJS to assign key-value pairs to a JSON object

I am currently working with a NodeJS script that receives data in the form of "key, value" pairs and I need to transform this data into a JSON object. The data is obtained using SNMP where the key corresponds to the OID. My goal is to efficiently map thes ...