(
operation: FfmpegOperation,
inputs: MediaFile[],
options: FfmpegOptions = {}
)
| 248 | * All inputs/outputs are buffers; temp files are created and cleaned up internally. |
| 249 | */ |
| 250 | export async function runFfmpegOperation( |
| 251 | operation: FfmpegOperation, |
| 252 | inputs: MediaFile[], |
| 253 | options: FfmpegOptions = {} |
| 254 | ): Promise<FfmpegResult> { |
| 255 | if (inputs.length === 0) { |
| 256 | throw new Error('At least one input file is required') |
| 257 | } |
| 258 | |
| 259 | if (operation === 'probe') { |
| 260 | return { probe: await probeMedia(inputs[0]) } |
| 261 | } |
| 262 | |
| 263 | return withTempDir(async (dir) => { |
| 264 | const inputPaths = await Promise.all(inputs.map((f, i) => writeInput(dir, f, i))) |
| 265 | |
| 266 | switch (operation) { |
| 267 | case 'overlay_audio': |
| 268 | case 'mux': |
| 269 | return overlayAudio(dir, inputPaths, options) |
| 270 | case 'mix_audio': |
| 271 | return mixAudio(dir, inputPaths, options) |
| 272 | case 'concat': |
| 273 | return concat(dir, inputPaths) |
| 274 | case 'trim': |
| 275 | return trim(dir, inputPaths[0], inputs[0], options) |
| 276 | case 'scale_pad': |
| 277 | return scalePad(dir, inputPaths[0], options) |
| 278 | case 'overlay_image': |
| 279 | return overlayImage(dir, inputPaths, options) |
| 280 | case 'add_text': |
| 281 | return addText(dir, inputPaths[0], options) |
| 282 | case 'fade': |
| 283 | return fade(dir, inputPaths[0], inputs[0], options) |
| 284 | case 'extract_audio': |
| 285 | return extractAudio(dir, inputPaths[0], options) |
| 286 | case 'convert': |
| 287 | return convert(dir, inputPaths[0], options) |
| 288 | case 'thumbnail': |
| 289 | return thumbnail(dir, inputPaths[0], options) |
| 290 | default: |
| 291 | throw new Error(`Unsupported ffmpeg operation: ${operation}`) |
| 292 | } |
| 293 | }) |
| 294 | } |
| 295 | |
| 296 | async function readOut(outputPath: string, ext: string): Promise<FfmpegResult> { |
| 297 | const buffer = await fs.readFile(outputPath) |
no test coverage detected