| import { logger } from './logger'; |
| import { exec } from 'child_process'; |
| import { promisify } from 'util'; |
| import { writeFile, readFile, unlink } from 'fs/promises'; |
| import { join } from 'path'; |
| import { randomBytes } from 'crypto'; |
|
|
| const execAsync = promisify(exec); |
|
|
| |
| |
| |
| |
| |
| export async function convertToMp3IfNeeded(inputBuffer: Buffer, filename: string): Promise<{ buffer: Buffer; format: string }> { |
| |
| |
| if (!filename.toLowerCase().endsWith('.ogg') && !filename.toLowerCase().endsWith('.opus') && !filename.toLowerCase().endsWith('.oga')) { |
| return { buffer: inputBuffer, format: filename.split('.').pop()! }; |
| } |
|
|
| const tempId = randomBytes(8).toString('hex'); |
| const inputPath = join('/tmp', `in_${tempId}_${filename}`); |
| const outputPath = join('/tmp', `out_${tempId}.mp3`); |
|
|
| try { |
| logger.info(`[FFMPEG] Starting conversion for ${filename}...`); |
|
|
| |
| await writeFile(inputPath, inputBuffer); |
|
|
| |
| |
| |
| |
| |
| |
| |
| await execAsync(`ffmpeg -y -i "${inputPath}" -vn -ar 44100 -ac 1 -b:a 64k "${outputPath}"`); |
|
|
| |
| const mp3Buffer = await readFile(outputPath); |
| logger.info(`[FFMPEG] ✅ Successfully converted ${filename} to MP3.`); |
|
|
| return { buffer: mp3Buffer, format: 'mp3' }; |
|
|
| } catch (err: unknown) { |
| logger.error(`[FFMPEG] ⚠️ Conversion failed for ${filename}. Proceeding with original buffer. Error: ${(err instanceof Error ? (err instanceof Error ? err.message : String(err)) : String(err))}`); |
| |
| return { buffer: inputBuffer, format: filename.split('.').pop()! }; |
| } finally { |
| |
| unlink(inputPath).catch(() => { }); |
| unlink(outputPath).catch(() => { }); |
| } |
| } |
|
|