File size: 1,854 Bytes
05abd64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { spawn } from 'child_process';
import ffmpegStaticPath from 'ffmpeg-static';

const DEFAULT_MP3_BITRATE = process.env.TTS_MP3_BITRATE || '64k';

class AudioTranscodeService {
  constructor() {
    this.ffmpegCommand = ffmpegStaticPath || process.env.FFMPEG_PATH || 'ffmpeg';
  }

  async convertWavToMp3(wavBuffer) {
    if (!wavBuffer || wavBuffer.length === 0) {
      throw new Error('WAV buffer is empty');
    }

    return new Promise((resolve, reject) => {
      const ffmpeg = spawn(this.ffmpegCommand, [
        '-hide_banner',
        '-loglevel',
        'error',
        '-f',
        'wav',
        '-i',
        'pipe:0',
        '-vn',
        '-codec:a',
        'libmp3lame',
        '-b:a',
        DEFAULT_MP3_BITRATE,
        '-f',
        'mp3',
        'pipe:1'
      ]);

      const outputChunks = [];
      const errorChunks = [];

      ffmpeg.stdout.on('data', (chunk) => outputChunks.push(chunk));
      ffmpeg.stderr.on('data', (chunk) => errorChunks.push(chunk));

      ffmpeg.on('error', (error) => {
        reject(
          new Error(
            `Cannot run ffmpeg command "${this.ffmpegCommand}": ${error.message}`
          )
        );
      });

      ffmpeg.on('close', (code) => {
        if (code !== 0) {
          const stderr = Buffer.concat(errorChunks).toString('utf8').trim();
          reject(new Error(stderr || `ffmpeg exited with code ${code}`));
          return;
        }

        const mp3Buffer = Buffer.concat(outputChunks);
        if (!mp3Buffer.length) {
          reject(new Error('ffmpeg produced an empty MP3 output'));
          return;
        }

        resolve(mp3Buffer);
      });

      ffmpeg.stdin.write(wavBuffer);
      ffmpeg.stdin.end();
    });
  }
}

export default new AudioTranscodeService();