feat(video): add ffmpeg-backed video converter for mp4/webm/mov/avi/mkv
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import { register } from './registry.js';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
export const VIDEO_FORMATS = ['mp4', 'webm', 'mov', 'avi', 'mkv'];
|
||||
|
||||
const CODEC_ARGS = {
|
||||
mp4: ['-c:v', 'libx264', '-c:a', 'aac'],
|
||||
mov: ['-c:v', 'libx264', '-c:a', 'aac'],
|
||||
mkv: ['-c:v', 'libx264', '-c:a', 'aac'],
|
||||
webm: ['-c:v', 'libvpx-vp9', '-c:a', 'libopus'],
|
||||
avi: ['-c:v', 'mpeg4', '-c:a', 'libmp3lame'],
|
||||
};
|
||||
|
||||
export function registerVideoConverters() {
|
||||
for (const sourceFormat of VIDEO_FORMATS) {
|
||||
for (const targetFormat of VIDEO_FORMATS) {
|
||||
if (sourceFormat === targetFormat) continue;
|
||||
register({
|
||||
family: 'video',
|
||||
sourceFormat,
|
||||
targetFormat,
|
||||
convert: async (inputPath, outputPath, { quality, timeoutMs } = {}) => {
|
||||
const ffmpegPath = process.env.FFMPEG_PATH || 'ffmpeg';
|
||||
const args = ['-y', '-i', inputPath, ...CODEC_ARGS[targetFormat]];
|
||||
if (quality != null) {
|
||||
args.push('-vf', `scale=-2:${quality}`);
|
||||
}
|
||||
args.push(outputPath);
|
||||
await execFileAsync(ffmpegPath, args, { timeout: timeoutMs });
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user