192 lines
6.0 KiB
TypeScript
192 lines
6.0 KiB
TypeScript
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();
|