import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as smartffmpeg from '../ts/index.js'; let ffmpegInstance: smartffmpeg.SmartFfmpeg; tap.test('should create SmartFfmpeg instance', async () => { ffmpegInstance = new smartffmpeg.SmartFfmpeg(); expect(ffmpegInstance).toBeInstanceOf(smartffmpeg.SmartFfmpeg); }); // ==================== BUILDER API TESTS ==================== tap.test('should create FfmpegCommand via create()', async () => { const command = ffmpegInstance.create(); expect(command).toBeInstanceOf(smartffmpeg.FfmpegCommand); }); tap.test('should create FfmpegCommand via input() shorthand', async () => { const command = ffmpegInstance.input('/path/to/input.mp4'); expect(command).toBeInstanceOf(smartffmpeg.FfmpegCommand); }); tap.test('should build correct args with builder API', async () => { const args = ffmpegInstance.create() .input('/input.mp4') .videoCodec('libx264') .audioCodec('aac') .videoBitrate('1M') .audioBitrate('128k') .size(1920, 1080) .fps(30) .crf(23) .preset('fast') .output('/output.mp4') .getArgs('/output.mp4'); expect(args).toContain('-i'); expect(args).toContain('/input.mp4'); expect(args).toContain('-c:v'); expect(args).toContain('libx264'); expect(args).toContain('-c:a'); expect(args).toContain('aac'); expect(args).toContain('-b:v'); expect(args).toContain('1M'); expect(args).toContain('-b:a'); expect(args).toContain('128k'); expect(args).toContain('-crf'); expect(args).toContain('23'); expect(args).toContain('-preset'); expect(args).toContain('fast'); expect(args).toContain('-r'); expect(args).toContain('30'); console.log('Builder API generates correct ffmpeg arguments'); }); tap.test('should support video filters', async () => { const args = ffmpegInstance.create() .input('/input.mp4') .scale(1280, 720) .flipHorizontal() .output('/output.mp4') .getArgs('/output.mp4'); expect(args).toContain('-vf'); const vfIndex = args.indexOf('-vf'); const filterString = args[vfIndex + 1]; expect(filterString).toInclude('scale=1280:720'); expect(filterString).toInclude('hflip'); console.log('Video filters work correctly'); }); tap.test('should support audio options', async () => { const args = ffmpegInstance.create() .input('/input.mp4') .noVideo() .audioCodec('libmp3lame') .audioBitrate('320k') .sampleRate(44100) .audioChannels(2) .volume(1.5) .format('mp3') .getArgs('/output.mp3'); expect(args).toContain('-vn'); expect(args).toContain('-c:a'); expect(args).toContain('libmp3lame'); expect(args).toContain('-ar'); expect(args).toContain('44100'); expect(args).toContain('-ac'); expect(args).toContain('2'); expect(args).toContain('-af'); expect(args).toContain('-f'); expect(args).toContain('mp3'); console.log('Audio extraction with builder works correctly'); }); tap.test('should support seek and duration', async () => { const args = ffmpegInstance.create() .input('/input.mp4') .seek(10) .duration(30) .output('/output.mp4') .getArgs('/output.mp4'); expect(args).toContain('-ss'); expect(args).toContain('-t'); console.log('Seek and duration work correctly'); }); // ==================== WEB STREAMS API TESTS ==================== tap.test('should return Web ReadableStream from toStream()', async () => { // Just verify the method signature and types - don't execute const command = ffmpegInstance.input('/input.mp4') .videoCodec('libx264') .format('mp4'); // Verify getArgs works (doesn't execute ffmpeg) const args = command.getArgs('pipe:1'); expect(args).toContain('-f'); expect(args).toContain('mp4'); console.log('toStream() method returns correct type signature'); }); tap.test('should accept Uint8Array input', async () => { const uint8Input = new Uint8Array([0, 1, 2, 3, 4]); // Dummy data const command = ffmpegInstance.input(uint8Input, { format: 'mp4' }) .videoCodec('libx264') .format('webm'); // Just verify args are built correctly for memory input const args = command.getArgs('pipe:1'); expect(args).toContain('-i'); expect(args).toContain('pipe:0'); // Memory input uses stdin console.log('Uint8Array input accepted correctly'); }); tap.test('should build correct args for memory output', async () => { const args = ffmpegInstance.input('/input.mp4') .videoCodec('libx264') .format('webm') .getArgs('pipe:1'); expect(args).toContain('-f'); expect(args).toContain('webm'); expect(args).toContain('pipe:1'); console.log('Memory output args built correctly'); }); // ==================== LEGACY API TESTS ==================== tap.test('should get available encoders', async () => { const encoders = await ffmpegInstance.getEncoders(); expect(encoders).toBeArray(); expect(encoders.length).toBeGreaterThan(0); // Common encoders should be available expect(encoders).toContain('libx264'); console.log(`Found ${encoders.length} encoders`); }); tap.test('should get available decoders', async () => { const decoders = await ffmpegInstance.getDecoders(); expect(decoders).toBeArray(); expect(decoders.length).toBeGreaterThan(0); console.log(`Found ${decoders.length} decoders`); }); tap.test('should get available formats', async () => { const formats = await ffmpegInstance.getFormats(); expect(formats).toBeArray(); expect(formats.length).toBeGreaterThan(0); // Common formats should be available expect(formats).toContain('mp4'); expect(formats).toContain('mp3'); console.log(`Found ${formats.length} formats`); }); tap.test('should run raw ffmpeg command', async () => { const result = await ffmpegInstance.runRaw(['-version']); expect(result.stdout).toInclude('ffmpeg'); console.log('FFmpeg version info retrieved successfully'); }); tap.test('should run raw ffprobe command', async () => { const result = await ffmpegInstance.runProbeRaw(['-version']); expect(result.stdout).toInclude('ffprobe'); console.log('FFprobe version info retrieved successfully'); }); // IMPORTANT: Always end with tap.start() export default tap.start();