javascript - Skriv eller strömma ljudfil (live-röst) till en variabel som binär data i Node.js


Jag arbetar med ljudströmmar i Node.js. För tillfället har min kod inte utils.promisfy och jag har 3 steg av den. Så efter den andra .pipe skriver jag filen till disk i wav ljudformat med nödvändiga parametrar.

Kodexempel nedan:

import { FileWriter } from 'wav';

const filename = `./${Date.now()}-${userId}.wav`;
const encoder = new OpusEncoder(16000, 1);

  receiver
    .subscribe(userId, {
      end: {
        behavior: EndBehaviorType.AfterSilence,
        duration: 100,
      },
    })
    // OpusDecodingStream is a custom class, which convert audio, like a gzip stage for file.
   .pipe(new OpusDecodingStream({}, encoder))
   .pipe(
      // Writes wav file to disk, also can be replaces with FileRead, part of wav module
      new FileWriter(filename, {
        channels: 1,
        sampleRate: 16000,
      }),
    );

Problemet är: Jag behöver överföra (inte streama!) den resulterande ljudfilen i binärt format via axios POST-metod. Så jag antar att det är lite fel att skriva filen på disk istället för att skriva den i en variabel, och efter att strömmen slutar, skicka den direkt till den önskade URL:en. Något (logiskt) som jag skulle vilja se:

// other code

const fileStringBinary = await receiver
    .subscribe(userId, {
      end: {
        behavior: EndBehaviorType.AfterSilence,
        duration: 100,
      },
    })
   .pipe(new OpusDecodingStream({}, encoder))
   .pipe(
      return new FileWriter(filename, {
        channels: 1,
        sampleRate: 16000,
      }),
    );

await axios.post('https://url.com', {
  data: fileStringBinary 
});

Tyvärr är jag inte så bra på streams och särskilt inte på ljud, så jag letar efter lite hjälp eller några användbara råd skulle vara välkomna för mig.

Jag förstår att jag kunde skriva min fil till en katalog, hitta den där, läsa igen med node:steam createReadStream och sedan POSTa den till den önskade URL:en. Det är inte vad jag behöver. Jag skulle vilja hoppa över dessa onödiga steg med att skriva och sedan läsa. Jag tror att det finns ett sätt att omvandla strömmen till binärt format och skriva ner det i en JS-variabel.

Svar #1

Det var lite knepigt ändå, men jag antar att jag klurade ut det:

const stream = receiver
    .subscribe(userId, {
        end: {
            behavior: EndBehaviorType.AfterSilence,
            duration: 100,
        },
    })
    .pipe(
        new opus.OggLogicalBitstream({
            opusHead: new opus.OpusHead({
                channelCount: 2,
                sampleRate: 48000,
            }),
            pageSizeControl: {
                maxPackets: 10,
            },
            crc: false,
        }),
    );

const data = [];

stream.on('data', (chunk) => {
    data.push(chunk);
});

stream.on('end', async () => {
    try {
        const response = await axios.post(
            `https://url.com${postParams}`,
            Buffer.concat(data),
            {
                headers: {
                    Authorization: `Api-Key ${token}`,
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
            },
        );

        console.log(response);
    } catch (e) {
        console.log(e);
    }
});

Tyvärr har jag inte hittat en bättre lösning än att använda den gammaldags events-modellen med data och på end. Mitt fungerande fall är kopplat till Discord.js röstinspelning utan fil och att använda ström för röstigenkänning.

Jag blir glad om någon kan ge en lösning med bättre syntax, och i så fall kommer jag att acceptera detta svar som lösta.