javascriptnode.jsffmpeg

Getting wav buffer from stdout


I am trying to get a downsampled audio so that I can use it for an hotword detection API. In the solution I am currently using, the audio is correctly converted and the API is able to recognize the content of the audio file. However, I am constantly forced to write temporary output files. I have tried several times to use "pipe:1" in ffmpeg to output the converted audio as a stream to stdout, but it has always given me errors.

function downsampleAudio(pcmBuffer) {
    return new Promise((resolve, reject) => {
        const inputStream = new PassThrough();
        inputStream.end(pcmBuffer);

        let filePath = path.join(__dirname, "output.wav")

        const ffmpeg = spawn("ffmpeg", [
            "-f", "s16le",   
            "-ar", "48000",  
            "-ac", "1",     
            "-i", "pipe:0",  
            "-ar", "16000",  
            "-ac", "1",      
            "-c:a", "pcm_s16le", 
            filePath 
        ]);
                    
        ffmpeg.stdin.on('error', (error) => {
            reject(new Error('Errore nello stream stdin di ffmpeg: ' + error.message));
        });

        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`Il processo ffmpeg è terminato con codice ${code}`));
            } else {
                console.log('Conversione completata con successo');
                const waveBuffer = fs.readFileSync(filePath);
                fs.unlinkSync(filePath);
                resolve(waveBuffer)
            }
        });

        inputStream.pipe(ffmpeg.stdin);
    });
}

Can anyone help me figure out how to correctly use ffmpeg to output the audio as a stream to stdout without errors? Thanks in advance!


Solution

  • Since I was using "FilePath" as the output, ffmpeg automatically set the output format to WAV. When I tried to set stdout as the output, ffmpeg could no longer recognize the output format because I forgot to specify it (I'm stupid, it was 5 AM where I am). Anyway, specifying WAV as the format worked.

    function downsampleAudio(pcmBuffer) {
    return new Promise((resolve, reject) => {
        const inputStream = new PassThrough();
        let chunks = [];
        inputStream.end(pcmBuffer);
    
        const ffmpeg = spawn("ffmpeg", [
            "-f", "s16le",   
            "-ar", "48000",  
            "-ac", "1",     
            "-i", "pipe:0",  
            "-f", "wav",     
            "-ar", "16000",  
            "-ac", "1",      
            "-c:a", "pcm_s16le", 
            "pipe:1" 
        ]);
    
        ffmpeg.stdin.on('error', (error) => {
            reject(new Error('Errore nello stream stdin di ffmpeg: ' + error.message));
        });
    
        ffmpeg.on('close', (code) => {
            if (code !== 0) {
                reject(new Error(`Il processo ffmpeg è terminato con codice ${code}`));
            } else {
                resolve(Buffer.concat(chunks));
            }
        });
    
        inputStream.pipe(ffmpeg.stdin);
    
        ffmpeg.stdout.on('data', (chunk) => {
            chunks.push(chunk);
        });
    });
    }