Repository: Mintplex-Labs/anything-llm
File: collector/utils/WhisperProviders/localWhisper.js (JavaScript)

Code before:

    return true;
  }

  async #convertToWavAudioData(sourcePath) {
    try {
      let buffer;
      const wavefile = require("wavefile");
      const { FFMPEGWrapper } = require("./ffmpeg");
      const ffmpeg = new FFMPEGWrapper();
      const outFolder = path.resolve(__dirname, `../../storage/tmp`);
      if (!fs.existsSync(outFolder))
        fs.mkdirSync(outFolder, { recursive: true });

      const outputFile = path.resolve(outFolder, `${v4()}.wav`);
      const success = await ffmpeg.convertAudioToWav(sourcePath, outputFile);
      if (!success)
        throw new Error(
          "[Conversion Failed]: Could not convert file to .wav format!"
        );

      const chunks = [];
      const stream = fs.createReadStream(outputFile);
      for await (let chunk of stream) chunks.push(chunk);
      buffer = Buffer.concat(chunks);
      fs.rmSync(outputFile);

      const wavFile = new wavefile.WaveFile(buffer);
      this.#validateAudioFile(wavFile);

      // Although we use ffmpeg to convert to the correct format (16k hz 32f),
      // different versions of ffmpeg produce different results based on the
      // environment. To ensure consistency, we convert to the correct format again.
      wavFile.toBitDepth("32f");
      wavFile.toSampleRate(16000);

      let audioData = wavFile.getSamples();
      if (Array.isArray(audioData)) {
        if (audioData.length > 1) {
          const SCALING_FACTOR = Math.sqrt(2);

          // Merge channels into first channel to save memory
          for (let i = 0; i < audioData[0].length; ++i) {
            audioData[0][i] =
              (SCALING_FACTOR * (audioData[0][i] + audioData[1][i])) / 2;
          }
        }
        audioData = audioData[0];
      }

      return audioData;

Review comment (suggestion):
Taking a second look at this code (i know it was in code previously) it might just make more sense to read the whole file into a buffer without chunking and looping it. Less overhead.

Just readFile it directly with no encoding and we should have a buffer.

Code after:

    return true;
  }

  async #convertToWavAudioData(sourcePath) {
    try {
      let buffer;
      const wavefile = require("wavefile");
      const { FFMPEGWrapper } = require("./ffmpeg");
      const ffmpeg = new FFMPEGWrapper();
      const outFolder = path.resolve(__dirname, `../../storage/tmp`);
      if (!fs.existsSync(outFolder))
        fs.mkdirSync(outFolder, { recursive: true });

      const outputFile = path.resolve(outFolder, `${v4()}.wav`);
      const success = ffmpeg.convertAudioToWav(sourcePath, outputFile);
      if (!success)
        throw new Error(
          "[Conversion Failed]: Could not convert file to .wav format!"
        );

      buffer = fs.readFileSync(outputFile);
      fs.rmSync(outputFile);

      const wavFile = new wavefile.WaveFile(buffer);
      try {
        this.#validateAudioFile(wavFile);
      } catch (error) {
        this.#log(`Audio validation failed: ${error.message}`);
        throw new Error(`Invalid audio file: ${error.message}`);
      }

      // Although we use ffmpeg to convert to the correct format (16k hz 32f),
      // different versions of ffmpeg produce different results based on the
      // environment. To ensure consistency, we convert to the correct format again.
      wavFile.toBitDepth("32f");
      wavFile.toSampleRate(16000);

      let audioData = wavFile.getSamples();
      if (Array.isArray(audioData)) {
        if (audioData.length > 1) {
          const SCALING_FACTOR = Math.sqrt(2);

          // Merge channels into first channel to save memory
          for (let i = 0; i < audioData[0].length; ++i) {
            audioData[0][i] =
              (SCALING_FACTOR * (audioData[0][i] + audioData[1][i])) / 2;
          }
        }
        audioData = audioData[0];
      }