sox.js icon indicating copy to clipboard operation
sox.js copied to clipboard

Is it possible to get output audio data in a variable without saving it on disk?

Open Catsvilles opened this issue 6 years ago • 5 comments

I just want to apply a few audio effects to a file and store result in a variable and pass it to the next function. Would it be possible with this package or overall with Sox? Thank you!

Catsvilles avatar Jun 26 '19 08:06 Catsvilles

You might be able to get the audio file as a stream, and then pipe it into gzip or something like that.

It's not possible with this package. However, this package is a thin wrapper on top of sox. You might be able to use sox-stream.

Or you could use require('child_process').spawn to launch sox like this:

sox [inputargs] - [outputargs] - [effectsargs]

(keep the hyphens. That tells sox that you're using stdin and stdout for the stream.)

If the first step is transcoding, then give sox an input file instead of an input stream. sox will be more reliable with an input file.

sox [inputargs] [inputfilename] [outputargs] - [effectsargs]

ArtskydJ avatar Jun 26 '19 14:06 ArtskydJ

@ArtskydJ thanks for getting back to me! "sox-stream" - sounds like a good solution. But before getting started I would like to know how will it work when we talk about "stream", I mean, can I just apply effects an audio file and immediately get the result in a variable as base64 or something or I will have to wait until the file is "played" and only then I will get the result? Sorry, if this is a bit silly question, just getting started here. :) Thank you!

Catsvilles avatar Jun 27 '19 09:06 Catsvilles

A stream is a node.js stream. To learn more about them, I recommend reading this: https://github.com/substack/stream-handbook#introduction TLDR, it's a way to work on chunks of data instead of the whole thing.

A stream will give you the results in chunks almost immediately, and if you're transcoding a 3 minute song, it should take less than 30 seconds for the whole stream to come through. A stream doesn't flow at the speed that the song would play. It streams as fast as sox will output, which should be faster than 1x.

If you want to buffer the entire stream, then I recommend using https://www.npmjs.com/package/simple-concat to turn the stream into a buffer. This is easier to conceptualize.

It would look something like this:

var sox = require('sox-stream')
var concat = require('simple-concat')
var fs  = require('fs')
 
var src = fs.createReadStream('song.flac')
var lowerVolume = sox({
    input: {
        volume: 0.8
    },
    output: {
        type: "flac"
    }
})
var dest = simpleConcat(function (err, buffer) {
    // do stuff with your node.js buffer of a mp3/wav/flac/whatever file
    // see https://nodejs.org/api/buffer.html
})

src
    .pipe(lowerVolume)
    .pipe(dest)

ArtskydJ avatar Jun 30 '19 03:06 ArtskydJ

@ArtskydJ Hi, thank you very much for getting back to me! I started using "sox-stream" and for now I just tried to apply effects to file and write it to disc but all I managed to get are empty files. It appears exactly when I'm adding effects with params (tried multiple of them with different params and all the possible syntax ways). Here is the example of what I'm doing:

var src = fs.createReadStream('input/1.wav')
var transform = sox({
        input: { type: 'wav' },
	output: { type: 'wav' },
	effects: [
		'speed 1.5 swap'
	]
})

var dest = fs.createWriteStream('song11.wav')
src.pipe(transform).pipe(dest)

transform.on('error', function (err) {
	console.log('oh no! ' + err.message)
})

transform.on('finish', function handler() {
  console.log('Finished');
})

Without adding effects it works perfect. There are not much examples of "transform", so maybe I'm doing something wrong? What are my options here? P.S. I noticed sox-stream already comes with "concat-stream" module, will try to use it before getting to "simple-concat".

Catsvilles avatar Jul 10 '19 08:07 Catsvilles

Sorry for the late response...

I don't know why you are getting empty files. I'm not sure what your options are. I would expect the effects to work. However, the documented effects might not have even been tested.

You might want to try a simpler effect than changing the speed. If you change the speed, it probably has to wait until the stream is complete. But if you just do effects: 'swap' then maybe it will not have to wait until the end of the stream.

ArtskydJ avatar Jul 19 '19 03:07 ArtskydJ