Devin Baker
Devin Baker

Reputation: 11

Merging two or more audio streams, and writing them

Firstly, I do not need to concat them. I need them to be written simultaneously in to the same file. Detailed: I'm trying to record voices, its working but when there's more than 1 is speaking the output is getting corrupted (because I don't know how to merge opus data, also i'm not able to use web-audio-api).

Here is my code:

AudioStream Class:

const stream = require('stream');

function AudioStream(options) { 
    stream.Readable.call(this, options);
}

AudioStream.prototype = Object.create(stream.Readable.prototype);
AudioStream.prototype.constructor = stream.Readable;
AudioStream.prototype._read = function() {};
AudioStream.prototype.write = function(chunk) {
    this.push(chunk);
};

module.exports = AudioStream;

Here is the code that doesn't work:

const { opus } = require('prism-media');
//const { pipeline } = require('stream');
const AudioStream = require('./utils/stream/AudioStream');

const receiver = connection.receiver;
const audioStream = new AudioStream();

const oggStream = new opus.OggLogicalBitstream({
    opusHead: new opus.OpusHead({
        channelCount: 2,
        sampleRate: 48000,
    }),
    pageSizeControl: {
        maxPackets: 10,
    },
});

audioStream.pipe(oggStream);
oggStream.on('data', (chunk) => {
    console.log(chunk)
    out.write(chunk);
});

receiver.speaking.on('start', userId => {
    if(!users.includes(userId)) {
        users.push(userId);
        const opusStream = receiver.subscribe(userId, {
            end: {
                behavior: EndBehaviorType.Manual,
            },
        });

        // oggStream.pipe(audioStream);
                    
        opusStream.on('data', (chunk) => {
            //console.log(chunk);
            audioStream.pushData(chunk)
        });
    }
});

Upvotes: 1

Views: 889

Answers (1)

Murat Colyaran
Murat Colyaran

Reputation: 2189

It wouldn't be much practical but you can write the streams to files, and merge them with FFmpeg

command:

ffmpeg -i first.wav -i second.wav -filter_complex "[0][1]amerge=inputs=2,pan=stereo|FL<c0+c1|FR<c2+c3[a]" -map "[a]" output.wav

node.js usage:

import { exec } from 'child_process'; // Or const { exec } = require('child_process'); if you are using javascript
const mergeAudios= (firstAudio: string, secondAudio: string, output: string) => {

    return new Promise((resolve, reject) => {
        exec(
    "ffmpeg -i " + firstAudio + "-i " + secondAudio + ' -filter_complex "[0][1]amerge=inputs=2,pan=stereo|FL<c0+c1|FR<c2+c3[a]" -map "[a]" ' + output,
    (error, stdout, stderr) => {
            if (error) {
                reject(error)
                return;
            } else {
                resolve(null);
            }
        });
    })

}

Upvotes: 1

Related Questions