2

In order to convert PCM audio to MP3 I'm using the following:

function spawnFfmpeg() {
    var args = [
        '-f', 's16le',
        '-ar', '48000',
        '-ac', '1',
        '-i', 'pipe:0',
        '-acodec', 'libmp3lame',
        '-f', 'mp3',
        'pipe:1'
    ];

    var ffmpeg = spawn('ffmpeg', args);

    console.log('Spawning ffmpeg ' + args.join(' '));

    ffmpeg.on('exit', function (code) {
        console.log('FFMPEG child process exited with code ' + code);
    });

    ffmpeg.stderr.on('data', function (data) {
        console.log('Incoming data: ' + data);
    });

    return ffmpeg;
}

Then I pipe everything together:

writeStream = fs.createWriteStream( "live.mp3" );
var ffmpeg = spawnFfmpeg();
stream.pipe(ffmpeg.stdin);
ffmpeg.stdout.pipe(/* destination */); 

The thing is... Now I want to merge (overlay) two streams into one. I already found how to do it with ffmpeg: How to overlay two audio files using ffmpeg

But, the ffmpeg command expects two inputs and so far I'm only able to pipe one input stream into the pipe:0 argument. How do I pipe two streams in the spawned command? Would something like ffmpeg -i pipe:0 -i pipe:0... work? How would I pipe the two incoming streams with PCM data (since the command expects two inputs)?

Keyne Viana
  • 6,194
  • 2
  • 24
  • 55

1 Answers1

1

You could use named pipes for this, but that isn't going to work on all platforms.

I would instead do the mixing in Node.js. Since your audio is in normal PCM samples, that makes this easy. To mix, you simply add them together.

The first thing I would do is convert your PCM samples to a common format... 32-bit float. Next, you'll have to decide how you want to handle cases where both channels are running at the same time and both are carrying loud sounds such that the signal will "clip" by exceeding 1.0 or -1.0. One option is to simply cut each channel's sample value in half before adding them together.

Another option, depending on your desired output, is to let it exceed the normal range and pass it to FFmpeg. FFmpeg can take in 32-bit float samples. There, you can apply proper compression/limiting to bring the signal back under clipping before encoding to MP3.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • @KeyneViana What you really need to do in this case is just switch to the live remote then, correct? There are a lot of solutions for doing this (Liquidsoap is popular, along with the various solutions built on top of it), but I'm not a fan of any of them. I'm building my own system for this which enables sample-accurate cuts from location to location. In fact, you can have one remote DJ hand off to another remote DJ, and the new DJ can mix and beat match to the previous. All live. It's still in development however and not ready for general use. – Brad Nov 24 '17 at 18:24
  • @KeyneViana Got it, so you want to have Auto DJ, but have someone drop in with their microphone and talk while music is playing? – Brad Nov 24 '17 at 20:12
  • The synchronized part is an unsolved problem. That's why I'm building software to do this... as far as I know, nobody has solved it otherwise. You actually need to shift the clock master from one place to another, and back again. That requires going back in time, which means a buffer of at least 2x the latency between the endpoints needs to be built up, and re-built after switches are complete. (This can be done by interpolating periodically, inserting samples that aren't there.) – Brad Nov 27 '17 at 17:08
  • I'm able to synchronize mic and music joining it on the browser and sending to liquidsoap/icecast. The files are stored on the server, so they are streamed via socket to the browser. I'm using MediaSource for this, but got stuck in another problem and opened a bounty for this question that still unanswered: https://stackoverflow.com/questions/23301496/how-to-keep-a-live-mediasource-video-stream-in-sync If you have any idea around this issue, please drop a line there. – Keyne Viana Dec 15 '17 at 21:34
  • @KeyneViana I'm available for consulting, if required. Contact me at brad@audiopump.co for more information. – Brad Dec 15 '17 at 23:57