Playback on iPhone devices and Safari experiences a 50% reduction with AudioWorklet

I recently developed a basic audio recorder that utilizes the AudioWorkletAPI. While the playback functions smoothly on Chrome, it seems to have issues on Safari and iPhone devices (including Chrome on iPhone) where half of the audio is missing. Specifically, only the first 20% and the last 30% of the audio can be heard.

You can check out the live example here:

Take a look at the audio worklet code below:

class RecorderProcessor extends AudioWorkletProcessor {
  bufferSize = 4096;
  // 1. Track the current buffer fill level
  _bytesWritten = 0;

  // 2. Create a buffer of fixed size
  _buffer = new Float32Array(this.bufferSize);

  constructor() {
    super();
    this.initBuffer();
  }

  initBuffer() {
    this._bytesWritten = 0;
  }

  isBufferEmpty() {
    return this._bytesWritten === 0;
  }

  isBufferFull() {
    return this._bytesWritten === this.bufferSize;
  }

  process(inputs) {
    // Grabbing the 1st channel similar to ScriptProcessorNode
    this.append(inputs[0][0]);

    return true;
  }

  append(channelData) {
    if (this.isBufferFull()) {
      this.flush();
    }

    if (!channelData) return;

    for (let i = 0; i < channelData.length; i++) {
      this._buffer[this._bytesWritten++] = channelData[i];
    }
  }

  flush() {
    // trim the buffer if ended prematurely
    this.port.postMessage(
      this._bytesWritten < this.bufferSize
        ? this._buffer.slice(0, this._bytesWritten)
        : this._buffer
    );
    this.initBuffer();
  }
}

registerProcessor('recorder.worklet', RecorderProcessor);

And here's the code responsible for initiating/stopping the recording and encoding it into WAV format:

let sampleRate = 3000;

// More code continues...

Answer №1

After extensive testing, I can confirm that there are significant issues with MacOS 12.6 and Safari when it comes to audio recording. The recordings end up scrambled, frames are skipped, and the chunk order is completely messed up. On iOS 16.0.3 (iPhone XS), the problem is slightly less severe - the recording starts off fine for about 4 seconds before skipping frames and continuing with some disruptions.
Even after trying out the latest Safari Developer Preview on Mac OS (2022.10.13), the same issues persist.

Interestingly, using the deprecated "scriptProcessor" feature does prevent frame skipping and scrambling, but unfortunately results in poor quality recordings for me.

All of these tests were conducted using the SEPIA web-audio framework available at: https://github.com/SEPIA-Framework/sepia-web-audio.

If a WebKit Bug-Report has not been filed yet, it may be necessary to create one to address these issues effectively.

Answer №2

I encountered the same issue with similar code. Currently, my only workaround is to switch to mediaRecorder for encoded recording and handle the pcm/wav conversion on the server side.

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

Import a JSON file into Parse by reading and parsing it to store in the database

I am currently facing a challenge with parsing JSON data in my Parse Cloud function. After fetching the JSON file, I need to parse the data and populate one of my classes with the results. However, I'm having trouble figuring out how to properly parse ...

Ways to incorporate a dynamic HTML form that allows for input elements to be added both horizontally and vertically while maintaining connected lines

Looking to design a form that showcases HTML elements in both vertical and horizontal positions, with lines connecting them as seen in this example: https://i.sstatic.net/jB12f.png. Can anyone offer guidance on how to achieve this? Thanks! ...

Error encountered when initializing NextJS Firebase Authentication App

I'm encountering challenges with implementing Firebase authentication using Google Provider in NextJS. I have set up the necessary environment variables and successfully established a connection to Firebase. However, I'm running into an issue whe ...

Changing return values with Jest mocks in TypeScript

Here I am again with a very straightforward example. In summary, I require a different response from the mocked class. Below is my basic class that returns an object: class Producer { hello() { return { ...

Tips for managing an event using the bxSlider callback API

I am currently using bxSlider to create a slideshow on my website. However, I now want to implement a manually controlled slideshow that also displays text content related to each image below the slideshow: Here is the code I have so far: <!--SlideSho ...

What is the best way to set the input type file to null when deleting an image in Vue?

My form allows users to upload an image, and everything was functioning properly until I encountered an issue. When I remove an image and try to upload the same image again, the @change function is not triggered. I am unable to reset the file value to null ...

Despite the presence of data, MongoDB is not returning any values

I am currently working on a code that utilizes $geoNear to find the closest transit stop to a given GPS coordinate. The issue I am facing is that the result sometimes returns undefined, even though I have confirmed that the data exists in the STOPS collect ...

extract specific data from JSON using JavaScript

Dealing with JSON data can be tricky, especially when working with multiple sets of information to choose from. When I inspect the data in my JavaScript code using console.log(contacts.data["all"]);, I can see the returned objects clearly. Here's a ...

Can you explain the contrast between moving an object versus shifting its controller within a xib view?

When working in Xcode, what distinguishes between dragging a Table View and dragging a Table View Controller onto a view in a XIB file? Similarly, what sets apart dragging a Tab Bar from dragging a Tab Bar Controller? ...

Placing a material UI Radio button within a row cell on a table

Here is the current design snapshot: https://i.sstatic.net/yRFWD.png I am working with Material UI's radio button component and I want to ensure that each row in the table can be selected only once. Although I am able to select a single row using the ...

Unable to retrieve data from Meteor find query

I have a collection created in collections.js portfolioItems = new Mongo.Collection('portfolioitems'); This collection is then subscribed to in subscriptions.js Meteor.subscribe('portfolioitems'); And published in publications.js M ...

Implementing image loading within an accordion component using React and Material UI

I'm working with a React Accordion component using Material UI. Each time I open a tab in the Accordion, I want to load different images from another div that is located outside of the Accordion. Here is the current code snippet: export default funct ...

What's the alternative now that Observable `of` is no longer supported?

I have a situation where I possess an access token, and if it is present, then I will return it as an observable of type string: if (this.accessToken){ return of(this.accessToken); } However, I recently realized that the of method has been deprecated w ...

Is it possible for an AngularJS directive to compile a fresh element that has a second directive assigned to it?

UPDATE: All directives listed below will now require ng-model bindings to be applied in the elements they generate, targeting the controller assigned to the page. The code has been modified to reflect this. I am exploring the creation of dynamic HTML usin ...

Launching a modal using a method in Vue.js that includes constantly changing content

I am currently developing a feature in my VueJs component that involves opening a modal when a certain condition becomes true, and then retrieving data from a controller to display in the modal. After searching online, I have not been able to find clear i ...

What are the steps for integrating a CMS with my unique website design?

Currently, I am in the process of creating a unique website for a client using my own combination of html, css, and JavaScript. There is also a possibility that I may incorporate vueJS into the design. The client has expressed a desire to have the ability ...

What reasons underlie the existence of various methods for importing Modules in JavaScript?

I'm confused about the distinctions when it comes to importing a JavaScript module in various ways such as: CommonJS ES5 ES6 NodeJS Typescript What is the reason for having multiple methods of importing JavaScript modules? Is the concept of a "modu ...

Tips on invoking a JSP and Servlet from JavaScript by passing in a parameter

Check out the code below for calling JavaScript functions: <td><input type="button" name="edit" value="Edit" onclick="editRecord(<%=rs.getString(1)%>);" ></td> <td><input type="button" name="delete" value="Delete" onclic ...

Tips for capturing the current terminal content upon keypress detection?

After successfully installing the terminal on a test page, I am looking to highlight matching parentheses within it. This is similar to what is done in this example: I have a working solution in place and now need to integrate it with the terminal. ...

Upcoming API and backend developments

When working with the NEXT project, API Routes provide the ability to create an API endpoint within a Next.js application. This can be achieved by creating a function in the pages/api directory following this format: // req = HTTP incoming message, res = H ...