Is there a way to combine several WAV audio blobs into one cohesive file?

Issue I'm Facing:

I am attempting to combine multiple blob audio files into a single blob and then download it on the page.

My Attempts So Far:

I have tried to merge the Audio blobs using the following methods:

Method - 1:

const url = window.URL.createObjectURL(new Blob(fullBlobArray), {
                    type: 'audio/*'
                });
const a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                a.href = url;
                a.download = "testing.wav";
                a.click();
                URL.revokeObjectURL(url);
                a.remove();

Method - 2 (Utilizing ConcatenateBlobs.js plugin - ConcatenateJS)

ConcatenateBlobs(fullBlobArray, 'audio/wav', function (fullBlob) {
                    const url = window.URL.createObjectURL(fullBlob);
                    const a = document.createElement("a");
                    document.body.appendChild(a);
                    a.style = "display: none";
                    a.href = url;
                    a.download = "testing.wav";
                    a.click();
                    URL.revokeObjectURL(url);
                    a.remove();

                    //Close the window after download.
                    window.close();

Explanation of Output:

If you have these audio blobs:

[audio1, audio2, audio3]

After executing the above code for download, only the Audio from the first file (i.e. audio1 ) is being played. However, the full blob's size encompasses the total size of audio1 + audio2 + audio3

I am unable to identify where the issue lies. Your assistance in resolving this matter would be greatly appreciated.

Answer №1

At last, I have discovered a solution! Credit goes to this informative article on StackOverflow. A big thanks to the authors for putting in the effort to create this valuable resource.

I want to extend my gratitude to those who commented out (@Bergi, @Zac, @Peter Krebs in the comments) highlighting the importance of formatting the blob according to WAV Format.

If you are looking to merge multiple WAV files into a single file, below is the code snippet:

wav_merger.js

// Insert code here
// More code snippets can be added

custom_script.js

// In this segment, we extract buffer from blobs and trigger download
getBufferFromBlobs(fullBlobArray).then(function (singleBlob) {
    const url = window.URL.createObjectURL(singleBlob);
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    a.href = url;
    a.download = "testing.wav";
    a.click();
    URL.revokeObjectURL(url);
    a.remove();
});

Answer №2

I encountered a similar issue and want to express my gratitude to @Vikash for bringing it up here. Currently, I am utilizing the ConcatenateBlobs.js script to concatenate wav blobs, which seems to only function correctly on Chrome. While your solution is commendable, I found the source code to be slightly lengthy. Therefore, I attempted to modify ConcatenateBlobs.js by addressing the file length discrepancy in the header. Fortunately, my modifications were successful:

    function ConcatenateBlobs(blobs, type, callback) {
        var buffers = [];

        var index = 0;

        function readAsArrayBuffer() {
            if (!blobs[index]) {
                return concatenateBuffers();
            }
            var reader = new FileReader();
            reader.onload = function(event) {
                buffers.push(event.target.result);
                index++;
                readAsArrayBuffer();
            };
            reader.readAsArrayBuffer(blobs[index]);
        }

        readAsArrayBuffer();


        function audioLengthTo32Bit(n) {
            n = Math.floor(n);
            var b1 = n & 255;
            var b2 = (n >> 8) & 255;
            var b3 = (n >> 16) & 255;
            var b4 = (n >> 24) & 255;
         
            return [b1, b2, b3, b4];
        }
        function concatenateBuffers() {
            var byteLength = 0;
            buffers.forEach(function(buffer) {
                byteLength += buffer.byteLength;
            });

            var tmp = new Uint8Array(byteLength);
            var lastOffset = 0;
            var newData;
            buffers.forEach(function(buffer) {
                if (type=='audio/wav' && lastOffset >  0) newData = new Uint8Array(buffer, 44);
                else newData = new Uint8Array(buffer);
                tmp.set(newData, lastOffset);
                lastOffset += newData.length;
            });
            if (type=='audio/wav') {
                tmp.set(audioLengthTo32Bit(lastOffset - 8), 4);
                tmp.set(audioLengthTo32Bit(lastOffset - 44), 40); // update audio length in the header
            }
            var blob = new Blob([tmp.buffer], {
                type: type
            });
            callback(blob);         
            
        }
    }

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

Guide on utilizing exported API endpoint in Node and Express

Seeking a deeper understanding of express and its utilization of various endpoints. Recently came across an example of an endpoint that reads in a json file, demonstrated as follows: const fs = require('fs'); const path = require('path&apos ...

The steps to display a partial view within another view in React Native

Attempting to show the View after calling alert("Hi") in the renderMoreView function has been challenging for me. The alert works fine, but displaying the View is where I am encountering issues. class Main extends Component { state = { moreButton: f ...

The absence of data in a c# web api controller is causing issues with jQuery AJAX post requests

When I am sending data to a c# web api controller, I use the following method: $.ajax({ type: "POST", url: "menuApi/menu/Cost", data: JSON.stringify(order), contentType: "application/json", success: function (data) { window.alert(&apo ...

What is the process for using AJAX and PHP to upload an image file?

I'm facing an issue where I want to insert an uploaded image into a database with user details for a profile picture. The output I receive currently shows {"current_field":null,"field_count":null,"lengths":null,"num_rows":null,"type":null}. How can th ...

Having difficulty creating the probot.github app due to an error: The removal of the programmatic API in npm version 8.0.0 causing failure

Currently, I am facing an issue while attempting to set up the probot.github app using the command npx create-probot-app my-first-app which can be found at: . My system is running on the latest node version v19.3.0 with npm version 9.2.0. However, upon exe ...

The initial value for the `useState` is not defined at the

Here's a simplified version of my requirement that demonstrates the issue. The ColorBox component receives a prop called "isVisible" from the ShowColorComponent component, which is used to initially set the state of the ColorBox.visible variable. impo ...

Enhance the app.get response by integrating data fetched from an http.get request

Currently, I am utilizing express and passing the path as a URL parameter. app.get("/download", function (req, res) { var location; var options = { host: 'example.com', port: 80, path: req.query.url.replace(/ /g, ...

Using JavaScript to Retrieve, Manipulate, and Merge JSON Data from Various Files

My knowledge of JavaScript is limited, but I am interested in uploading multiple JSON files, processing them, converting them to text, combining them, and downloading them into a single JS file. I have successfully achieved this for a single file, but I a ...

Error encountered while attempting to retrieve an environment variable: Invalid token found

I am currently facing an issue while trying to add an environment variable inside the .env file in my Nuxt project. The version of Nuxt.js I am using is 2.15.3 Below is a snippet from my nuxt.config.js: export default { publicRuntimeConfig: { baseU ...

Please refrain from submitting the form until the slow AJAX jQuery process has finished

My form is experiencing a delay of almost 4 seconds due to the Ajax jQuery I am using, which creates fields within the form. This delay causes some users to submit the form before the necessary fields are created. I need a way to prevent the form from bein ...

Unveiling the secret to accessing properties using v-if within a custom component template relocation

I'm currently working on an application that reveals a hidden div when the text "Create Test" is clicked. Everything works well when the code isn't placed inside the template of a component. This seems strange to me, what could be causing this is ...

Checking jquery validation on a field when it contains input

My form validation process involves using jquery validate as shown below: $("#formuser").validate({ rules: { accountname: { required: true, minlength: 6 }, T1: { required: true, ...

Transferring the link value to an AJAX function when the onclick event is triggered

I have a link containing some data. For example: <li><a href="" onclick="getcategory(this);"><?php echo $result22['category']; ?></a></li> I need this link to pass the value of $result22['category']; to ...

There appears to be a malfunction with WebRupee

I have incorporated the new rupee sign into my website to represent Indian currency. Below is the code snippet I used: For the script, I included " and also added the following: <span class="WebRupee">Rs.</span> 116,754.00 To style it using ...

Changing a button's value on click using PhoneGap

I've been working with phonegap and came across an issue with my buttons setup like this: <input id="my_button" type="button" onclick="my_function();"/> The goal is to capture the click event and change the button's value, my_function ( ...

Filtering rows of an HTML table that contain links in the `<href>` column data in real time

When using HTML and JavaScript, I have found a solution that works well for many of the columns I am working with. You can see the details on how to dynamically filter rows of an HTML table using JavaScript here. var filters=['hide_broj_pu',&apo ...

Tips for formatting a phone number using regular expressions in [Vue 2]

I am currently working on creating regex code that will meet the following requirements: Only allow the first character (0th index) in a string to be either a '+' symbol or a number (0-9). No non-numerical values (0-9) should be allowed anywhere ...

Exploring the capabilities of Vue.js, including the use of Vue.set()

Just starting out with Vuejs and I have a query regarding the correct approach to achieve what I want. My Objective I aim to have some dates stored in an array and be able to update them upon an event trigger. Initially, I attempted using Vue.set, which ...

Prevent the box from closing automatically after submitting a form using jQuery

Despite my efforts to keep a simple dialog box open after submitting a form, it continues to close. I tried using the preventDefault method in jQuery, but it didn't solve the issue. Below is the code snippet: $(document).ready(function(e) { $(&apo ...

Upon inserting Node 5, an error with the code EINVALIDTYPE occurred in npm

Recently, after I upgraded to Node 5, I've been encountering an error in the terminal every time I try running anything with npm. npm -v: 2.14.12 Desperately attempting to update npm to the latest version: MacBook-Pro-de-MarceloRS:promo-auto-loan ...