* Convert audio/video using FFmpeg
( inputBuffer: Buffer, mimeType: string, options: AudioExtractionOptions )
| 115 | * Convert audio/video using FFmpeg |
| 116 | */ |
| 117 | async function convertAudioWithFFmpeg( |
| 118 | inputBuffer: Buffer, |
| 119 | mimeType: string, |
| 120 | options: AudioExtractionOptions |
| 121 | ): Promise<AudioExtractionResult> { |
| 122 | // Create temporary files |
| 123 | const tempDir = os.tmpdir() |
| 124 | const inputExt = getExtensionFromMimeType(mimeType) |
| 125 | const outputFormat = options.outputFormat || 'mp3' |
| 126 | const inputFile = path.join(tempDir, `ffmpeg-input-${Date.now()}.${inputExt}`) |
| 127 | const outputFile = path.join(tempDir, `ffmpeg-output-${Date.now()}.${outputFormat}`) |
| 128 | |
| 129 | try { |
| 130 | // Write input buffer to temporary file |
| 131 | await fs.writeFile(inputFile, inputBuffer) |
| 132 | |
| 133 | // Get metadata for duration |
| 134 | let duration = 0 |
| 135 | try { |
| 136 | const metadata = await getAudioMetadataFromFile(inputFile) |
| 137 | duration = metadata.duration || 0 |
| 138 | } catch (error) { |
| 139 | // Metadata extraction failed, continue without duration |
| 140 | logger.warn('Failed to extract metadata:', error) |
| 141 | } |
| 142 | |
| 143 | // Convert using FFmpeg |
| 144 | await new Promise<void>((resolve, reject) => { |
| 145 | let command = ffmpeg(inputFile).toFormat(outputFormat).audioCodec(getAudioCodec(outputFormat)) |
| 146 | |
| 147 | // Apply audio options |
| 148 | if (options.channels) { |
| 149 | command = command.audioChannels(options.channels) |
| 150 | } |
| 151 | if (options.sampleRate) { |
| 152 | command = command.audioFrequency(options.sampleRate) |
| 153 | } |
| 154 | if (options.bitrate) { |
| 155 | command = command.audioBitrate(options.bitrate) |
| 156 | } |
| 157 | |
| 158 | command |
| 159 | .on('end', () => resolve()) |
| 160 | .on('error', (err) => reject(new Error(`FFmpeg error: ${err.message}`))) |
| 161 | .save(outputFile) |
| 162 | }) |
| 163 | |
| 164 | // Read output file |
| 165 | const outputBuffer = await fs.readFile(outputFile) |
| 166 | |
| 167 | return { |
| 168 | buffer: outputBuffer, |
| 169 | format: outputFormat, |
| 170 | duration, |
| 171 | size: outputBuffer.length, |
| 172 | } |
| 173 | } finally { |
| 174 | // Clean up temporary files |
no test coverage detected