nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.46k stars 279 forks source link

How to reuse a child process? #4173

Closed alexlarocca closed 1 year ago

alexlarocca commented 1 year ago

Details

Hello, I created a function that executes a command (Piper) to transform text into speech. It works but, each time I call it (on a Raspberry PI), the function takes more than 3 seconds to load the voice, and after that the creation of the wav file is very fast. Of course, this delay makes my function not usable since I call it a lot of time and I always I have to wait 3/4 seconds before to reproduce the speech.

Is there any way I can "preload" the voice file and reuse the process in order to save the load time? This is my first project with Node, so I'm inexperienced. Thanks

Node.js version

Not applicable.16.20.0

Example code

var voice = 'it-riccardo_fasol-x-low.onnx';
var filename = '/tmp/out.wav';
var cmd = 'echo "Ciao" | piper -m ' + voice + ' --output_file ' + fileName + ' && aplay ' + fileName;

exec(cmd, function(error) {
    if(error) {
        console.log('error while executing command ', cmd);
    }
});

Operating system

linux/raspian

Scope

code

Module and version

Not applicable.

marsonya commented 1 year ago

There is no way (and is not recommended) to store the child_process spawned. Although in your case, you should try and separate the voice loading and process execution. Load the voice once separately and then have a second function to spawn your child_processes.

tniessen commented 1 year ago

It seems that piper is responsible for the delay. There is nothing Node.js can do about the performance of piper on your system. Child processes cannot be reused.

I assume that piper loads the voice before it starts reading text from stdin. Thus, you could spawn the child process (without the echo command), let it load the voice, and then eventually write the text to the child process's stdin once you know what the input is. In other words, always keep a piper process alive but do not write to its stdin until you want to get an output file. As soon as one piper process ends, start a new one, even if you might not need it immediately.

Other than that, you could propose a more efficient command-line interface upstream. Perhaps piper could add a way to produce multiple outputs from separate inputs without having to load the voice multiple times.