DVD Integration

This commit is contained in:
2026-03-06 11:21:25 +00:00
parent 3abb53fb8e
commit e1a87af16a
20 changed files with 2900 additions and 697 deletions

View File

@@ -9,6 +9,44 @@ const { errorToMeta } = require('../utils/errorMeta');
const { setLogRootDir, getJobLogDir } = require('../services/logPathService');
const schemaFilePath = path.resolve(__dirname, '../../../db/schema.sql');
const LEGACY_PROFILE_SETTING_MIGRATIONS = [
{
legacyKey: 'mediainfo_extra_args',
profileKeys: ['mediainfo_extra_args_bluray', 'mediainfo_extra_args_dvd']
},
{
legacyKey: 'makemkv_rip_mode',
profileKeys: ['makemkv_rip_mode_bluray', 'makemkv_rip_mode_dvd']
},
{
legacyKey: 'makemkv_analyze_extra_args',
profileKeys: ['makemkv_analyze_extra_args_bluray', 'makemkv_analyze_extra_args_dvd']
},
{
legacyKey: 'makemkv_rip_extra_args',
profileKeys: ['makemkv_rip_extra_args_bluray', 'makemkv_rip_extra_args_dvd']
},
{
legacyKey: 'handbrake_preset',
profileKeys: ['handbrake_preset_bluray', 'handbrake_preset_dvd']
},
{
legacyKey: 'handbrake_extra_args',
profileKeys: ['handbrake_extra_args_bluray', 'handbrake_extra_args_dvd']
},
{
legacyKey: 'output_extension',
profileKeys: ['output_extension_bluray', 'output_extension_dvd']
},
{
legacyKey: 'filename_template',
profileKeys: ['filename_template_bluray', 'filename_template_dvd']
},
{
legacyKey: 'output_folder_template',
profileKeys: ['output_folder_template_bluray', 'output_folder_template_dvd']
}
];
let dbInstance;
@@ -484,6 +522,7 @@ async function openAndPrepareDatabase() {
await applySchemaModel(dbInstance, schemaModel);
await seedDefaultSettings(dbInstance);
await migrateLegacyProfiledToolSettings(dbInstance);
await removeDeprecatedSettings(dbInstance);
await ensurePipelineStateRow(dbInstance);
const syncedLogRoot = await configureRuntimeLogRootFromSettings(dbInstance, { ensure: true });
@@ -573,6 +612,72 @@ async function seedDefaultSettings(db) {
logger.info('seed:settings', { count: seeded });
}
async function readCurrentOrDefaultSettingValue(db, key) {
if (!key) {
return null;
}
return db.get(
`
SELECT
s.default_value AS defaultValue,
v.value AS currentValue,
COALESCE(v.value, s.default_value) AS effectiveValue
FROM settings_schema s
LEFT JOIN settings_values v ON v.key = s.key
WHERE s.key = ?
LIMIT 1
`,
[key]
);
}
async function migrateLegacyProfiledToolSettings(db) {
let copiedCount = 0;
for (const migration of LEGACY_PROFILE_SETTING_MIGRATIONS) {
const legacyRow = await readCurrentOrDefaultSettingValue(db, migration.legacyKey);
if (!legacyRow) {
continue;
}
for (const targetKey of migration.profileKeys || []) {
const targetRow = await readCurrentOrDefaultSettingValue(db, targetKey);
if (!targetRow) {
continue;
}
const currentValue = targetRow.currentValue;
const defaultValue = targetRow.defaultValue;
const shouldCopy = (
currentValue === null
|| currentValue === undefined
|| String(currentValue) === String(defaultValue ?? '')
);
if (!shouldCopy) {
continue;
}
await db.run(
`
INSERT INTO settings_values (key, value, updated_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
ON CONFLICT(key) DO UPDATE SET
value = excluded.value,
updated_at = CURRENT_TIMESTAMP
`,
[targetKey, legacyRow.effectiveValue ?? null]
);
copiedCount += 1;
logger.info('migrate:legacy-tool-setting-copied', {
from: migration.legacyKey,
to: targetKey
});
}
}
if (copiedCount > 0) {
logger.info('migrate:legacy-tool-settings:done', { copiedCount });
}
}
async function ensurePipelineStateRow(db) {
await db.run(
`
@@ -584,7 +689,19 @@ async function ensurePipelineStateRow(db) {
}
async function removeDeprecatedSettings(db) {
const deprecatedKeys = ['pushover_notify_disc_detected'];
const deprecatedKeys = [
'pushover_notify_disc_detected',
'mediainfo_extra_args',
'makemkv_rip_mode',
'makemkv_analyze_extra_args',
'makemkv_rip_extra_args',
'handbrake_preset',
'handbrake_extra_args',
'output_extension',
'filename_template',
'output_folder_template',
'makemkv_backup_mode'
];
for (const key of deprecatedKeys) {
const result = await db.run('DELETE FROM settings_schema WHERE key = ?', [key]);
if (result?.changes > 0) {

View File

@@ -146,18 +146,6 @@ const defaultSchema = [
validation: { minLength: 1 },
orderIndex: 205
},
{
key: 'mediainfo_extra_args',
category: 'Tools',
label: 'Mediainfo Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für mediainfo.',
defaultValue: '',
options: [],
validation: {},
orderIndex: 206
},
{
key: 'makemkv_min_length_minutes',
category: 'Tools',
@@ -170,57 +158,6 @@ const defaultSchema = [
validation: { min: 1, max: 1000 },
orderIndex: 210
},
{
key: 'pipeline_max_parallel_jobs',
category: 'Tools',
label: 'Parallele Jobs',
type: 'number',
required: 1,
description: 'Maximale Anzahl parallel laufender Jobs. Weitere Starts landen in der Queue.',
defaultValue: '1',
options: [],
validation: { min: 1, max: 12 },
orderIndex: 211
},
{
key: 'makemkv_rip_mode',
category: 'Tools',
label: 'MakeMKV Rip Modus',
type: 'select',
required: 1,
description: 'mkv: direkte MKV-Dateien; backup: vollständige Blu-ray Struktur im RAW-Ordner.',
defaultValue: 'backup',
options: [
{ label: 'MKV', value: 'mkv' },
{ label: 'Backup', value: 'backup' }
],
validation: {},
orderIndex: 212
},
{
key: 'makemkv_analyze_extra_args',
category: 'Tools',
label: 'MakeMKV Analyze Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Analyze.',
defaultValue: '',
options: [],
validation: {},
orderIndex: 220
},
{
key: 'makemkv_rip_extra_args',
category: 'Tools',
label: 'MakeMKV Rip Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Rip.',
defaultValue: '',
options: [],
validation: {},
orderIndex: 230
},
{
key: 'handbrake_command',
category: 'Tools',
@@ -231,31 +168,7 @@ const defaultSchema = [
defaultValue: 'HandBrakeCLI',
options: [],
validation: { minLength: 1 },
orderIndex: 300
},
{
key: 'handbrake_preset',
category: 'Tools',
label: 'HandBrake Preset',
type: 'string',
required: 1,
description: 'Preset Name für -Z.',
defaultValue: 'H.264 MKV 1080p30',
options: [],
validation: { minLength: 1 },
orderIndex: 310
},
{
key: 'handbrake_extra_args',
category: 'Tools',
label: 'HandBrake Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Argumente.',
defaultValue: '--audio-lang-list deu,eng --first-audio --subtitle-lang-list deu,eng --first-subtitle --aencoder copy --audio-copy-mask ac3,eac3,dts --audio-fallback ac3 --encoder-preset slow --quality 18 --encoder-tune film --encoder-profile high --encoder-level 4.1',
options: [],
validation: {},
orderIndex: 320
orderIndex: 215
},
{
key: 'handbrake_restart_delete_incomplete_output',
@@ -267,15 +180,102 @@ const defaultSchema = [
defaultValue: 'true',
options: [],
validation: {},
orderIndex: 220
},
{
key: 'pipeline_max_parallel_jobs',
category: 'Tools',
label: 'Parallele Jobs',
type: 'number',
required: 1,
description: 'Maximale Anzahl parallel laufender Jobs. Weitere Starts landen in der Queue.',
defaultValue: '1',
options: [],
validation: { min: 1, max: 12 },
orderIndex: 225
},
{
key: 'mediainfo_extra_args_bluray',
category: 'Tools',
label: 'Mediainfo Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für mediainfo (Blu-ray).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 300
},
{
key: 'makemkv_rip_mode_bluray',
category: 'Tools',
label: 'MakeMKV Rip Modus',
type: 'select',
required: 1,
description: 'mkv: direkte MKV-Dateien; backup: vollständige Blu-ray Struktur im RAW-Ordner.',
defaultValue: 'backup',
options: [
{ label: 'MKV', value: 'mkv' },
{ label: 'Backup', value: 'backup' }
],
validation: {},
orderIndex: 305
},
{
key: 'makemkv_analyze_extra_args_bluray',
category: 'Tools',
label: 'MakeMKV Analyze Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Analyze (Blu-ray).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 310
},
{
key: 'makemkv_rip_extra_args_bluray',
category: 'Tools',
label: 'MakeMKV Rip Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Rip (Blu-ray).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 315
},
{
key: 'handbrake_preset_bluray',
category: 'Tools',
label: 'HandBrake Preset',
type: 'string',
required: 1,
description: 'Preset Name für -Z (Blu-ray).',
defaultValue: 'H.264 MKV 1080p30',
options: [],
validation: { minLength: 1 },
orderIndex: 320
},
{
key: 'handbrake_extra_args_bluray',
category: 'Tools',
label: 'HandBrake Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Argumente (Blu-ray).',
defaultValue: '--audio-lang-list deu,eng --first-audio --subtitle-lang-list deu,eng --first-subtitle --aencoder copy --audio-copy-mask ac3,eac3,dts --audio-fallback ac3 --encoder-preset slow --quality 18 --encoder-tune film --encoder-profile high --encoder-level 4.1',
options: [],
validation: {},
orderIndex: 325
},
{
key: 'output_extension',
key: 'output_extension_bluray',
category: 'Tools',
label: 'Ausgabeformat',
type: 'select',
required: 1,
description: 'Dateiendung für finale Datei.',
description: 'Dateiendung für finale Datei (Blu-ray).',
defaultValue: 'mkv',
options: [
{ label: 'MKV', value: 'mkv' },
@@ -285,28 +285,142 @@ const defaultSchema = [
orderIndex: 330
},
{
key: 'filename_template',
key: 'filename_template_bluray',
category: 'Tools',
label: 'Dateiname Template',
type: 'string',
required: 1,
description: 'Verfügbare Tokens: ${title}, ${year}, ${imdbId}.',
description: 'Verfügbare Tokens: ${title}, ${year}, ${imdbId} (Blu-ray).',
defaultValue: '${title} (${year})',
options: [],
validation: { minLength: 1 },
orderIndex: 340
orderIndex: 335
},
{
key: 'output_folder_template',
key: 'output_folder_template_bluray',
category: 'Tools',
label: 'Ordnername Template',
type: 'string',
required: 0,
description: 'Optional. Verfügbare Tokens: ${title}, ${year}, ${imdbId}. Leer = Dateiname-Template verwenden.',
description: 'Optional. Verfügbare Tokens: ${title}, ${year}, ${imdbId}. Leer = Dateiname-Template (Blu-ray).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 345
orderIndex: 340
},
{
key: 'mediainfo_extra_args_dvd',
category: 'Tools',
label: 'Mediainfo Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für mediainfo (DVD).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 500
},
{
key: 'makemkv_rip_mode_dvd',
category: 'Tools',
label: 'MakeMKV Rip Modus',
type: 'select',
required: 1,
description: 'mkv: direkte MKV-Dateien; backup: vollständige Disc-Struktur im RAW-Ordner.',
defaultValue: 'mkv',
options: [
{ label: 'MKV', value: 'mkv' },
{ label: 'Backup', value: 'backup' }
],
validation: {},
orderIndex: 505
},
{
key: 'makemkv_analyze_extra_args_dvd',
category: 'Tools',
label: 'MakeMKV Analyze Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Analyze (DVD).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 510
},
{
key: 'makemkv_rip_extra_args_dvd',
category: 'Tools',
label: 'MakeMKV Rip Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Parameter für Rip (DVD).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 515
},
{
key: 'handbrake_preset_dvd',
category: 'Tools',
label: 'HandBrake Preset',
type: 'string',
required: 1,
description: 'Preset Name für -Z (DVD).',
defaultValue: 'H.264 MKV 480p30',
options: [],
validation: { minLength: 1 },
orderIndex: 520
},
{
key: 'handbrake_extra_args_dvd',
category: 'Tools',
label: 'HandBrake Extra Args',
type: 'string',
required: 0,
description: 'Zusätzliche CLI-Argumente (DVD).',
defaultValue: '--audio-lang-list deu,eng --first-audio --subtitle-lang-list deu,eng --first-subtitle --aencoder copy --audio-copy-mask ac3,eac3,dts --audio-fallback ac3 --encoder-preset slow --quality 18 --encoder-tune film --encoder-profile high --encoder-level 4.1',
options: [],
validation: {},
orderIndex: 525
},
{
key: 'output_extension_dvd',
category: 'Tools',
label: 'Ausgabeformat',
type: 'select',
required: 1,
description: 'Dateiendung für finale Datei (DVD).',
defaultValue: 'mkv',
options: [
{ label: 'MKV', value: 'mkv' },
{ label: 'MP4', value: 'mp4' }
],
validation: {},
orderIndex: 530
},
{
key: 'filename_template_dvd',
category: 'Tools',
label: 'Dateiname Template',
type: 'string',
required: 1,
description: 'Verfügbare Tokens: ${title}, ${year}, ${imdbId} (DVD).',
defaultValue: '${title} (${year})',
options: [],
validation: { minLength: 1 },
orderIndex: 535
},
{
key: 'output_folder_template_dvd',
category: 'Tools',
label: 'Ordnername Template',
type: 'string',
required: 0,
description: 'Optional. Verfügbare Tokens: ${title}, ${year}, ${imdbId}. Leer = Dateiname-Template (DVD).',
defaultValue: '',
options: [],
validation: {},
orderIndex: 540
},
{
key: 'omdb_api_key',