0.16.1-5 Ebcode Fix / presets
Deploy Docs to GitHub Pages / Build Documentation (push) Has been cancelled
Deploy Docs to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled

This commit is contained in:
2026-04-30 12:37:32 +00:00
parent f9cf3cef09
commit 6fbc5395a1
24 changed files with 1131 additions and 784 deletions
+185 -32
View File
@@ -27,6 +27,7 @@ const { buildMediainfoReview, refreshAudioTrackActionsForPlanTitles } = require(
const { analyzePlaylistObfuscation, normalizePlaylistId } = require('../utils/playlistAnalysis');
const { errorToMeta } = require('../utils/errorMeta');
const userPresetService = require('./userPresetService');
const userPresetDefaultsService = require('./userPresetDefaultsService');
const thumbnailService = require('./thumbnailService');
const activationBytesService = require('./activationBytesService');
const { toBoolean } = require('../utils/validators');
@@ -8529,6 +8530,119 @@ function normalizeUserPresetForPlan(rawPreset) {
};
}
function resolveUserPresetDefaultSlotKey(mediaProfile, isSeriesSelection = false) {
const normalizedProfile = normalizeMediaProfile(mediaProfile);
if (normalizedProfile !== 'dvd' && normalizedProfile !== 'bluray') {
return null;
}
return `${normalizedProfile}_${isSeriesSelection ? 'series' : 'movie'}`;
}
async function applyConfiguredDefaultUserPresetToReviewPlan(reviewPlan, options = {}) {
const plan = reviewPlan && typeof reviewPlan === 'object'
? reviewPlan
: null;
if (!plan) {
return {
plan: reviewPlan,
applied: false,
slotKey: null,
presetId: null,
presetName: null
};
}
const existingUserPreset = normalizeUserPresetForPlan(plan?.userPreset || null);
if (existingUserPreset) {
return {
plan,
applied: false,
slotKey: null,
presetId: existingUserPreset.id || null,
presetName: existingUserPreset.name || null
};
}
const slotKey = resolveUserPresetDefaultSlotKey(options?.mediaProfile || null, Boolean(options?.isSeriesSelection));
if (!slotKey) {
return {
plan,
applied: false,
slotKey: null,
presetId: null,
presetName: null
};
}
try {
const defaultsMap = await userPresetDefaultsService.listDefaults();
const rawPresetId = defaultsMap && typeof defaultsMap === 'object'
? defaultsMap[slotKey]
: null;
const presetId = normalizePositiveInteger(rawPresetId);
if (!presetId) {
return {
plan,
applied: false,
slotKey,
presetId: null,
presetName: null
};
}
const preset = await userPresetService.getPresetById(presetId);
const normalizedPreset = normalizeUserPresetForPlan(preset);
if (!normalizedPreset) {
return {
plan,
applied: false,
slotKey,
presetId,
presetName: null
};
}
const presetMediaType = String(preset?.mediaType || '').trim().toLowerCase();
const normalizedProfile = normalizeMediaProfile(options?.mediaProfile || null);
const mediaTypeAllowed = presetMediaType === 'all'
|| !presetMediaType
|| presetMediaType === normalizedProfile;
if (!mediaTypeAllowed) {
return {
plan,
applied: false,
slotKey,
presetId,
presetName: normalizedPreset.name || null
};
}
return {
plan: {
...plan,
userPreset: normalizedPreset
},
applied: true,
slotKey,
presetId: normalizedPreset.id || presetId || null,
presetName: normalizedPreset.name || null
};
} catch (error) {
logger.warn('review:user-preset-default:resolve-failed', {
mediaProfile: options?.mediaProfile || null,
isSeriesSelection: Boolean(options?.isSeriesSelection),
error: errorToMeta(error)
});
return {
plan,
applied: false,
slotKey,
presetId: null,
presetName: null
};
}
}
function buildScriptDescriptorList(scriptIds, sourceScripts = []) {
const normalizedIds = normalizeScriptIdList(scriptIds);
if (normalizedIds.length === 0) {
@@ -18257,6 +18371,11 @@ class PipelineService extends EventEmitter {
options?.multipartSettingsLock || null
);
review = multipartLockResult.plan;
const reviewDefaultUserPresetResult = await applyConfiguredDefaultUserPresetToReviewPlan(review, {
mediaProfile,
isSeriesSelection: true
});
review = reviewDefaultUserPresetResult.plan;
resolvedSelectedTitleIds = normalizeReviewTitleIdList(review.selectedTitleIds || []);
resolvedPrimaryTitleId = normalizeReviewTitleId(review.encodeInputTitleId)
|| resolvedSelectedTitleIds[0]
@@ -18931,6 +19050,11 @@ class PipelineService extends EventEmitter {
options?.multipartSettingsLock || null
);
review = multipartLockResult.plan;
const reviewDefaultUserPresetResult = await applyConfiguredDefaultUserPresetToReviewPlan(review, {
mediaProfile,
isSeriesSelection: isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, analyzeContext)
});
review = reviewDefaultUserPresetResult.plan;
if (!Array.isArray(review.titles) || review.titles.length === 0) {
const error = new Error('Titel-/Spurprüfung aus RAW lieferte keine Titel.');
@@ -22014,29 +22138,26 @@ class PipelineService extends EventEmitter {
}
// Resolve user preset: explicit payload wins, otherwise preserve currently selected preset from encode plan.
const hasExplicitUserPresetSelection = !multipartSettingsLocked
&& Object.prototype.hasOwnProperty.call(options || {}, 'selectedUserPresetId');
const hasExplicitHandBrakePresetSelection = !multipartSettingsLocked
&& Object.prototype.hasOwnProperty.call(options || {}, 'selectedHandBrakePreset');
const rawHandBrakePreset = hasExplicitHandBrakePresetSelection
const hasUserPresetIdField = Object.prototype.hasOwnProperty.call(options || {}, 'selectedUserPresetId');
const hasHandBrakePresetField = Object.prototype.hasOwnProperty.call(options || {}, 'selectedHandBrakePreset');
const explicitUserPresetId = hasUserPresetIdField
? normalizePositiveInteger(options?.selectedUserPresetId)
: null;
const rawHandBrakePreset = hasHandBrakePresetField
? String(options?.selectedHandBrakePreset || '').trim()
: '';
const hasExplicitUserPresetSelection = !multipartSettingsLocked && explicitUserPresetId !== null;
const hasExplicitHandBrakePresetSelection = !multipartSettingsLocked && Boolean(rawHandBrakePreset);
let resolvedUserPreset = null;
if (hasExplicitUserPresetSelection) {
const rawUserPresetId = options?.selectedUserPresetId;
const userPresetId = rawUserPresetId !== null && rawUserPresetId !== undefined && String(rawUserPresetId).trim() !== ''
? Number(rawUserPresetId)
: null;
if (Number.isFinite(userPresetId) && userPresetId > 0) {
resolvedUserPreset = await userPresetService.getPresetById(userPresetId);
if (!resolvedUserPreset) {
const error = new Error(`User-Preset ${userPresetId} nicht gefunden.`);
error.statusCode = 404;
throw error;
}
resolvedUserPreset = await userPresetService.getPresetById(explicitUserPresetId);
if (!resolvedUserPreset) {
const error = new Error(`User-Preset ${explicitUserPresetId} nicht gefunden.`);
error.statusCode = 404;
throw error;
}
}
if ((!resolvedUserPreset || !hasExplicitUserPresetSelection) && hasExplicitHandBrakePresetSelection) {
if (!resolvedUserPreset && hasExplicitHandBrakePresetSelection) {
resolvedUserPreset = rawHandBrakePreset
? {
name: `HandBrake: ${rawHandBrakePreset}`,
@@ -22045,8 +22166,10 @@ class PipelineService extends EventEmitter {
}
: null;
}
if (!hasExplicitUserPresetSelection && !hasExplicitHandBrakePresetSelection) {
resolvedUserPreset = normalizeUserPresetForPlan(encodePlan?.userPreset || null);
if (!resolvedUserPreset) {
resolvedUserPreset = normalizeUserPresetForPlan(
planForConfirm?.userPreset || encodePlan?.userPreset || null
);
}
const confirmedPlan = {
@@ -22070,24 +22193,49 @@ class PipelineService extends EventEmitter {
const readyMediaProfile = this.resolveMediaProfileForJob(job, {
encodePlan: confirmedPlan
});
if (readyMediaProfile === 'converter' && !confirmedPlan.userPreset) {
const error = new Error('Bestätigung nicht möglich: Bitte ein User- oder HandBrake-Preset auswählen.');
const confirmSettings = await settingsService.getEffectiveSettingsMap(readyMediaProfile);
const confirmedConverterMediaType = String(
confirmedPlan?.converterMediaType || encodePlan?.converterMediaType || ''
).trim().toLowerCase();
const requiresExplicitPreset = readyMediaProfile === 'dvd'
|| readyMediaProfile === 'bluray'
|| (readyMediaProfile === 'converter' && confirmedConverterMediaType !== 'audio');
const planPresetName = String(
planForConfirm?.userPreset?.handbrakePreset
|| encodePlan?.userPreset?.handbrakePreset
|| planForConfirm?.selectors?.preset
|| encodePlan?.selectors?.preset
|| ''
).trim();
const planExtraArgs = String(
planForConfirm?.userPreset?.extraArgs
|| encodePlan?.userPreset?.extraArgs
|| planForConfirm?.selectors?.extraArgs
|| encodePlan?.selectors?.extraArgs
|| ''
).trim();
const effectivePresetName = String(
resolvedUserPreset?.handbrakePreset
|| rawHandBrakePreset
|| planPresetName
|| confirmSettings?.handbrake_preset
|| ''
).trim();
const effectiveExtraArgs = String(
resolvedUserPreset?.extraArgs
|| planExtraArgs
|| confirmSettings?.handbrake_extra_args
|| ''
).trim();
if (requiresExplicitPreset && !effectivePresetName && !effectiveExtraArgs) {
const error = new Error('Bestätigung nicht möglich: Kein Preset oder Extra-Args gesetzt. Bitte User-/HandBrake-Preset wählen oder passende Settings hinterlegen.');
error.statusCode = 400;
throw error;
}
const confirmSettings = await settingsService.getEffectiveSettingsMap(readyMediaProfile);
const actionDisplaySettings = {
...(confirmSettings && typeof confirmSettings === 'object' ? confirmSettings : {}),
handbrake_preset: String(
resolvedUserPreset?.handbrakePreset
|| confirmSettings?.handbrake_preset
|| ''
).trim() || null,
handbrake_extra_args: String(
resolvedUserPreset?.extraArgs
|| confirmSettings?.handbrake_extra_args
|| ''
).trim()
handbrake_preset: effectivePresetName || null,
handbrake_extra_args: effectiveExtraArgs
};
confirmedPlan.titles = refreshAudioTrackActionsForPlanTitles(
confirmedPlan.titles,
@@ -23315,6 +23463,11 @@ class PipelineService extends EventEmitter {
options?.multipartSettingsLock || null
);
enrichedReview = multipartLockResult.plan;
const reviewDefaultUserPresetResult = await applyConfiguredDefaultUserPresetToReviewPlan(enrichedReview, {
mediaProfile,
isSeriesSelection: effectiveIsSeriesDvdReview
});
enrichedReview = reviewDefaultUserPresetResult.plan;
const previousEncodePlan = options?.previousEncodePlan && typeof options.previousEncodePlan === 'object'
? options.previousEncodePlan
: null;