feat(video): wire video converters, resolution validation, and timeout into app.js/worker.js

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 22:01:58 +02:00
co-authored by Claude Sonnet 5
parent 9c1f857398
commit 457913d8d4
4 changed files with 121 additions and 1 deletions
+40
View File
@@ -11,6 +11,7 @@ import { createJob, getJobByUuid, getJobErrorLog } from '../src/jobs/jobReposito
import { registerImageConverters } from '../src/converters/image.js';
import { registerIcoConverter } from '../src/converters/ico.js';
import { registerEbookConverter } from '../src/converters/ebook.js';
import { registerVideoConverters } from '../src/converters/video.js';
import { processPendingJobs } from '../src/worker.js';
const { execFileMock } = vi.hoisted(() => ({ execFileMock: vi.fn() }));
@@ -23,6 +24,7 @@ beforeAll(async () => {
registerImageConverters();
registerIcoConverter();
registerEbookConverter();
registerVideoConverters();
config = { ...loadConfig(), storageDir: await fs.mkdtemp(path.join(os.tmpdir(), 'converter-worker-')) };
await ensureStorageDirs(config);
prisma = getPrismaClient(config);
@@ -227,4 +229,42 @@ describe('processPendingJobs', () => {
expect(options).toEqual({ timeout: config.ebookJobTimeoutMs });
expect(config.ebookJobTimeoutMs).not.toBe(60000);
});
it('converts a pending video job to done using config.videoJobTimeoutMs, not the default 60s timeout', async () => {
execFileMock.mockReset();
execFileMock.mockImplementation((file, args, options, callback) => {
writeFileSync(args[args.length - 1], 'fake converted video output');
callback(null, '', '');
});
const uuid = '22222222-2222-4222-8222-222222222222';
const inputFilePath = uploadPath(config, uuid, 'mp4');
await fs.writeFile(inputFilePath, 'fake mp4 content');
await createJob(prisma, {
uuid,
family: 'video',
sourceFormat: 'mp4',
targetFormat: 'webm',
originalFilename: 'clip.mp4',
inputPath: `${uuid}.mp4`,
inputMimeType: 'video/mp4',
inputSizeBytes: 17,
expiresAt: new Date(Date.now() + 3600 * 1000),
quality: 720,
});
await processPendingJobs(prisma, config);
const job = await getJobByUuid(prisma, uuid);
expect(job.status).toBe('done');
const [file, args, options] = execFileMock.mock.calls[0];
expect(file).toBe('ffmpeg');
expect(args).toEqual([
'-y', '-i', inputFilePath, '-c:v', 'libvpx-vp9', '-c:a', 'libopus', '-vf', 'scale=-2:720',
outputPath(config, uuid, 'webm'),
]);
expect(options).toEqual({ timeout: config.videoJobTimeoutMs });
expect(config.videoJobTimeoutMs).not.toBe(60000);
});
});