Cutting up the blob resulted in a lack of sound

I have been developing a small app that records user audio and transfers it to the back-end service using Angular.

Currently, I have successfully created an app where users can record audio, send it, and even download the file to listen for testing purposes.

However, I encountered an issue with larger audio files that exceed 10 seconds in duration. In order to handle this, I implemented code to slice the audio into smaller chunks. While I can segment the audio, store them in an array, and download them individually, I am facing difficulty playing these chunks. Only the first chunk plays, while the others cannot be opened or played.

This is the section of the code where I divide the blob into sub-blobs:

if (this.duration > this.audioLimitBeforeChunking) {
        let numChunks = this.duration/this.audioLimitBeforeChunking;
        Math.floor(numChunks/1000);
        console.log('numChunks is: ', numChunks);
        for (let index = 0; index <= numChunks; index++) {
            var byteEnd = Math.ceil((size/numChunks) * (index + 1));
            this.blobArray.push(blob.slice(this.byteIndex, byteEnd));
            this.byteIndex += (byteEnd - this.byteIndex);
        }
    }

This is where I handle downloading all the sub-blobs:

for (let i = 0; i <= this.blobArray.length; i++) {
      this.url = URL.createObjectURL(this.blobArray[i]);
      this.audioFile = new File([this.blobArray[i]], "I_like_apples" + i + ".wav");
      let postBody = {
        'file': this.audioFile,
        'user_token': '*******',
        'reference_text': '******',
        'model_id': '******'
      }
      console.log("inside sendData() component");
      this.httpService.getStatus(postBody).subscribe(
        (response:any) => {
          console.log(response)
        }
      )

      const a = document.createElement('a');
      a.style.display = 'none';
      a.href = this.url;
      a.download = 'test.wav';
      document.body.appendChild(a);
      a.click();
    }
  }

While I can play the first sub-blob, the subsequent ones cannot be opened or played. Any insights on what might be causing this issue? Am I overlooking something in my approach?

Answer №1

Splitting audio files into chunks for playback requires including the necessary .wav RIFF audio format metadata within each blob. This metadata allows browsers to interpret the file as audio and play it back. The first blob works because it contains the original metadata, while the others do not.

Creating this from scratch is no simple task.

A WAV (RIFF) file header is 44 bytes long and follows this format:

Positions Sample Value    Description
1 - 4 “RIFF”  File marked as a riff file, 1 byte per character.
5 - 8 File size (integer) Overall file size minus 8 bytes in bytes (32-bit integer). Usually filled after creation.
9 -12 “WAVE”  File Type Header, always "WAVE".
13-16 “fmt”   Format chunk marker with trailing null.
17-20 16  Length of format data as shown above.
21-22 1   Format type (1 for PCM) - 2 byte integer.
23-24 2   Number of Channels - 2 byte integer.
25-28 44100   Sample Rate - 32 byte integer. Common values are 44100 (CD), 48000 (DAT).
29-32 176400  (Sample Rate * BitsPerSample * Channels) / 8.
33-34 4   (BitsPerSample * Channels) / 8.1 - 8 bit mono2 - 8 bit stereo/16 bit mono4 - 16 bit stereo
35-36 16  Bits per sample
37-40 “data”  “data” chunk header marking the start of the data section.
41-44 File size (data)    Size of the data section.

Consider using a tool like https://github.com/rochars/wavefile to help generate these blobs.

Alternatively, you might try adding the first 44 bytes of the original file format to each of your blobs - although I cannot guarantee this method will work.

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

Tips for properly panning across the canvas

I added event listeners to capture mouse movement, clicks, and releases in my code. canvas.addEventListener('mousemove', onMouseMove, false); canvas.addEventListener('mousedown', onMouseDown,false); canvas.addEventListener('mouseu ...

When utilizing the catch function callback in Angular 2 with RxJs, the binding to 'this' can trigger the HTTP request to loop repeatedly

I have developed a method to handle errors resulting from http requests. Here is an example of how it functions: public handleError(err: any, caught: Observable<any>): Observable<any> { //irrelevant code omitted this.logger.debug(err);//e ...

What is the best way to ensure a JavaScript event is only activated after another event has been triggered on the same element?

I have set up a mouseleave event for the select tag. However, I want this event to only happen when a user clicks on the select tag first and then moves their mouse away from it. function loseFocus() { var dateSelect=document.querySelector('[ ...

Issue: [$compile:multidir] encountered for Component Directive that includes an Attribute Directive

In search of a 'sticky' directive that can trigger the addition of a css class to an element when it reaches the top of a page and also notify the changes in its state, I have declared a scope like { onStickyChange: '&' }. My goal i ...

Error message "getSystemErrorName is not a function" is received while using the Google Data Studio community connector local development tool

Currently, I am utilizing the guidelines provided in the Google Data Connector's local development resource to establish a fresh community-connector. However, upon executing the command npx @google/dscc-gen connector, I encounter an error stating getS ...

Checkbox radio buttons with mandatory selection

I'm facing a challenge with radio buttons in my form. While checkboxes could easily solve this issue, the customer specifically requested radio buttons. Here is the relevant section of the form: <label> <span>I Agree*</span> ...

I am confused as to why I am receiving npm warnings for angularfire 2.0.0-beta.2 when I have only been using version 2.0.0-beta.0

Currently, I am working on a project that involves using angularfire 2.0.0-beta.0 as specified in the package.json file... "angularfire2": "^2.0.0-beta.0" ...however, upon running npm install, I have been receiving npm warnings related to angularfire 2.0 ...

Bidirectional data flow connecting controller with external directive

My system: Picture a manager for an online shopping cart: app.controller('CartCtrl', function ($scope) { $scope.data = [ { id:0, title:'product1' }, { id:1, ti ...

Unable to utilize the Object.values method with an object in TypeScript

I am attempting to create an array of values from all the keys within an object by using the Object.values(obj) function, but I encountered the following error message: No overload matches this call. Overload 1 of 2, '(o: { [s: string]: string; } | ...

On production, Heroku fails to load JavaScript files, only allowing CSS files to be loaded. However, the files load successfully when

I've been struggling to find a solution to my problem, so I'm reaching out for some help. I am in the process of deploying my node (express) app to Heroku, but I've encountered an issue where only CSS files from my public folder are being t ...

The Angular 2 router UMD file, router.umd.js, was not found

Trying to run an Angular 2 project and implement @angular/router is proving to be a bit challenging. Everything seems to be working fine, until the moment I attempt: import { provideRouter, RouterConfig } from '@angular/router'; As it tries to ...

Converting constants into JavaScript code

I've been diving into typescript recently and came across a simple code snippet that defines a constant variable and logs it to the console. const versionNuber : number = 1.3; console.log(versionNuber); Upon running the tsc command on the file, I no ...

Using JavaScript arrays to populate an HTML form

I am new to JavaScript, although I have some experience with Python, and I find it challenging to integrate JS with HTML. I am attempting to convert an array into an HTML dropdown list, but I am struggling to make it function correctly. <HEAD> ...

"Troubleshooting: Android - getSharedPreferences method not Resolving

Hello, I am facing an issue with getSharedPreferences not resolving. I have searched for solutions extensively but nothing seems to fix it. How can I implement getSharedPreferences in onclick inside ViewHolder? Here is the code snippet from MyHolder.class ...

What could be preventing the fill color of my SVG from changing when I hover over it?

I am currently utilizing VueJS to design an interactive map showcasing Japan. The SVG I am using is sourced from Wikipedia. My template structure is illustrated below (The crucial classes here are the prefecture and region classes): <div> <svg ...

Navigate through the website by transforming the arrow and clicking the link

I am struggling with transitioning my arrow from › (right) to ˇ (down) when toggled. I can't figure out where to place it. If you look at Menu 1 > Submenu 1 > Text with hyperlink I want the 'Text with Hyperlink' to be clickable on ...

What is the method for accessing an image in JavaScript?

Currently, I am developing a currency converter for a gaming marketplace and I would like the users to be able to generate images using JavaScript. While most of the work is completed, I am facing an issue where the images are not displaying properly and i ...

Issues with menu and content styling in Ionic 4 on iOS device

My issue can be better explained with a GIF: https://i.sstatic.net/miRVH.gif The main page is "Challenges" and it has a link to "Challenge creation". The problem occurs when you visit that link and then return to the "Challenges" page (refer to the GIF). ...

Discord.js messageCollector filtering options

I am looking to set up a MessageCollector with multiple users in Discord. Here is what I have so far: const collector = new Discord.MessageCollector(channel, m => m.author.id === "123456789" || m.author.id === "978654321" , { max: 2000, maxMa ...

Changing Font Awesome Icon with React onClick Event

My dilemma involves a listing of items, each accompanied by a "caret-down" icon. My goal is for clicking on the icon to reveal more information beneath the item, while changing the icon to "caret-up". Subsequently, clicking on the icon again should hide th ...