'use strict'; const { execSync, spawnSync } = require('child_process'); const path = require('path'); const fs = require('fs'); const FFMPEG = process.env.FFMPEG_PATH || 'ffmpeg'; const SAMPLES = { test1: 'tests/samples/media/toshiba/Radarr/Film Test (2023)/Film Test (2023).mkv', test2: 'tests/samples/media/toshiba/Sonarr/Naruto S01/Naruto S01E01.mkv', test3: 'tests/samples/test3_ultrawide.mkv', test4: 'tests/samples/test4_subtitles.mkv', }; function run(cmd) { console.log(`\n>> ${cmd}\n`); const result = spawnSync(cmd, { shell: true, stdio: 'inherit' }); if (result.status !== 0) { console.error(`Command failed with exit ${result.status}`); process.exit(1); } } function ensureDir(filePath) { fs.mkdirSync(path.dirname(filePath), { recursive: true }); } // Test 1 — skip if already generated if (!fs.existsSync(SAMPLES.test1)) { console.log('Generating Test 1: 23.976fps Film (AC3 ITA 448k + EAC3 ENG 640k)...'); ensureDir(SAMPLES.test1); run([ FFMPEG, '-y', '-f', 'lavfi', '-i', 'color=c=blue:s=1920x1080:r=24000/1001:d=30', '-f', 'lavfi', '-i', 'sine=f=440:r=48000:d=30', '-f', 'lavfi', '-i', 'sine=f=660:r=48000:d=30', '-map', '0:v', '-map', '1:a', '-map', '2:a', '-c:v', 'libx264', '-crf', '28', '-preset', 'ultrafast', '-c:a:0', 'ac3', '-b:a:0', '448k', '-ac:a:0', '6', '-metadata:s:a:0', 'language=ita', '-c:a:1', 'eac3', '-b:a:1', '640k', '-ac:a:1', '6', '-metadata:s:a:1', 'language=eng', `"${SAMPLES.test1}"`, ].join(' ')); console.log('Test 1 OK.\n'); } else { console.log('Test 1 already exists — skipping.\n'); } // Test 2 — EAC3 ITA 640k 5.1 at 25fps (DTS is experimental in FFmpeg) // Note: DTS logic is fully covered by unit tests with synthetic streams. // For integration, we use EAC3 640k which triggers series clamping: 640>=384 -> Opus=384 console.log('Generating Test 2: 25fps Anime EAC3 ITA 640k 5.1 (Naruto)...'); ensureDir(SAMPLES.test2); run([ FFMPEG, '-y', '-f', 'lavfi', '-i', 'color=c=green:s=1280x720:r=25:d=30', '-f', 'lavfi', '-i', 'sine=f=660:r=48000:d=30', '-map', '0:v', '-map', '1:a', '-c:v', 'libx264', '-crf', '28', '-preset', 'ultrafast', '-c:a:0', 'eac3', '-b:a:0', '640k', '-ac:a:0', '6', '-metadata:s:a:0', 'language=ita', `"${SAMPLES.test2}"`, ].join(' ')); console.log('Test 2 OK.\n'); // Test 3 — Ultrawide 3840x1600 console.log('Generating Test 3: Ultrawide 3840x1600...'); ensureDir(SAMPLES.test3); run([ FFMPEG, '-y', '-f', 'lavfi', '-i', 'color=c=red:s=3840x1600:r=24:d=10', '-f', 'lavfi', '-i', 'sine=f=440:r=48000:d=10', '-map', '0:v', '-map', '1:a', '-c:v', 'libx264', '-crf', '28', '-preset', 'ultrafast', '-c:a', 'aac', '-b:a', '128k', '-metadata:s:a:0', 'language=eng', `"${SAMPLES.test3}"`, ].join(' ')); console.log('Test 3 OK.\n'); // Test 4 — SRT forced + SRT SDH console.log('Generating Test 4: Subtitles (SRT forced + SRT SDH)...'); ensureDir(SAMPLES.test4); const srtContent = '1\n00:00:01,000 --> 00:00:03,000\nTest subtitle line 1\n\n2\n00:00:04,000 --> 00:00:06,000\nTest subtitle line 2\n'; const tmpSrt = 'tests/samples/tmp_sub.srt'; fs.writeFileSync(tmpSrt, srtContent); run([ FFMPEG, '-y', '-f', 'lavfi', '-i', 'color=c=gray:s=1920x1080:r=25:d=30', '-f', 'lavfi', '-i', 'sine=f=440:r=48000:d=30', '-i', `"${tmpSrt}"`, '-i', `"${tmpSrt}"`, '-map', '0:v', '-map', '1:a', '-map', '2:s', '-map', '3:s', '-c:v', 'libx264', '-crf', '28', '-preset', 'ultrafast', '-c:a', 'aac', '-b:a', '128k', '-metadata:s:a:0', 'language=ita', '-c:s:0', 'srt', '-metadata:s:s:0', 'language=ita', '-disposition:s:0', 'forced', '-c:s:1', 'srt', '-metadata:s:s:1', 'language=ita', '-disposition:s:1', 'hearing_impaired', `"${SAMPLES.test4}"`, ].join(' ')); try { fs.unlinkSync(tmpSrt); } catch(_) {} console.log('Test 4 OK.\n'); console.log('All test files generated. Run: node tests/run-tests.js --skip-transcode');