feat: Tdarr Local Flow Plugin Suite v1.0

7 atomic plugins for automated x265 transcoding pipeline:
- utility/mediaAnalyzerGOP    : GOP calc, FPS detection, film/series/anime routing
- utility/setAnimationFlag    : manual animation flag override
- utility/extractChaptersXml  : mkvextract chapters to XML
- audio/audioSelectorClamping : codec scoring, clamped Opus bitrates, 2 outputs
- audio/backupSourceAudio     : lossless DTS/TrueHD ITA backup (-c:a copy)
- subtitles/extractSubtitlesAndOcr : SRT extract + SubtitleEdit OCR for PGS
- video/transcode2PassX265    : 2-pass x265, Lanczos 1080p bound, Opus mux

Test suite: 34 unit tests + 3 integration tests (FFmpeg real files)
FlowHelpers mock for local testing included
Docs: integration-guide.md with canvas wiring and deploy instructions
This commit is contained in:
PickleRick committed 2026-09-18 23:23:05 +02:00
commit c2074be826
19 files changed
+2134

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
'use strict';
/**
* test4-subtitles.js
* Validates: extractSubtitlesAndOcr produces correctly named SRT files.
* Source: MKV with 2 ITA SRT streams (forced + SDH).
* Expected: .ita.forced.srt and .ita.hearing_impaired.srt in source dir.
*/
const path = require('path');
const fs = require('fs');
const { buildMockArgs, cleanupWorkDir, assert } = require('../mock-tdarr-runtime');
const { plugin: subPlugin } = require('../../LocalFlowPlugins/subtitles/extractSubtitlesAndOcr/1.0.0/index');
const FILE = path.resolve('tests/samples/test4_subtitles.mkv');
const SOURCE_DIR = path.dirname(FILE);
const BASE_NAME = path.basename(FILE, '.mkv');
async function run() {
console.log('\n=== TEST 4: Subtitle Extraction (forced + SDH) ===\n');
const args = buildMockArgs({
filePath: FILE,
inputs: { subtitleEditPath: 'SubtitleEdit', languages: 'ita,eng' },
});
await subPlugin(args);
// Check that forced SRT was created
const forcedSrt = path.join(SOURCE_DIR, `${BASE_NAME}.ita.forced.srt`);
const sdhSrt = path.join(SOURCE_DIR, `${BASE_NAME}.ita.sdh.srt`);
console.log(' Checking for:', path.basename(forcedSrt));
assert(fs.existsSync(forcedSrt), `Forced SRT exists: ${path.basename(forcedSrt)}`);
console.log(' Checking for:', path.basename(sdhSrt));
// Note: disposition hearing_impaired maps to 'sdh' suffix
// If not found, check for .ita.default.srt variant (FFmpeg disposition naming may vary)
const sdhExists = fs.existsSync(sdhSrt);
const altSdhExists = fs.existsSync(path.join(SOURCE_DIR, `${BASE_NAME}.ita.default.srt`));
assert(sdhExists || altSdhExists, `SDH/hearing-impaired SRT exists`);
// Cleanup generated subtitle files
[forcedSrt, sdhSrt].forEach((f) => { try { fs.unlinkSync(f); } catch (_) {} });
cleanupWorkDir(args);
console.log('\n=== TEST 4 PASSED ===\n');
}
module.exports = run;