HandBrake
This commit is contained in:
@@ -17,6 +17,7 @@ const { ensureDir, sanitizeFileName, renderTemplate, findMediaFiles } = require(
|
||||
const { buildMediainfoReview } = require('../utils/encodePlan');
|
||||
const { analyzePlaylistObfuscation, normalizePlaylistId } = require('../utils/playlistAnalysis');
|
||||
const { errorToMeta } = require('../utils/errorMeta');
|
||||
const userPresetService = require('./userPresetService');
|
||||
|
||||
const RUNNING_STATES = new Set(['ANALYZING', 'RIPPING', 'ENCODING', 'MEDIAINFO_CHECK']);
|
||||
const REVIEW_REFRESH_SETTING_PREFIXES = [
|
||||
@@ -5583,6 +5584,21 @@ class PipelineService extends EventEmitter {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Resolve user preset if provided
|
||||
const rawUserPresetId = options?.selectedUserPresetId ?? null;
|
||||
const userPresetId = rawUserPresetId !== null && rawUserPresetId !== undefined
|
||||
? Number(rawUserPresetId)
|
||||
: null;
|
||||
let resolvedUserPreset = 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;
|
||||
}
|
||||
}
|
||||
|
||||
const confirmedPlan = {
|
||||
...planForConfirm,
|
||||
postEncodeScriptIds: selectedPostEncodeScripts.map((item) => Number(item.id)),
|
||||
@@ -5598,7 +5614,15 @@ class PipelineService extends EventEmitter {
|
||||
postEncodeChainIds: selectedPostEncodeChainIds,
|
||||
preEncodeChainIds: selectedPreEncodeChainIds,
|
||||
reviewConfirmed: true,
|
||||
reviewConfirmedAt: nowIso()
|
||||
reviewConfirmedAt: nowIso(),
|
||||
userPreset: resolvedUserPreset
|
||||
? {
|
||||
id: resolvedUserPreset.id,
|
||||
name: resolvedUserPreset.name,
|
||||
handbrakePreset: resolvedUserPreset.handbrakePreset,
|
||||
extraArgs: resolvedUserPreset.extraArgs
|
||||
}
|
||||
: null
|
||||
};
|
||||
const inputPath = isPreRipMode
|
||||
? null
|
||||
@@ -5622,6 +5646,7 @@ class PipelineService extends EventEmitter {
|
||||
+ ` Pre-Encode-Ketten: ${selectedPreEncodeChainIds.length > 0 ? selectedPreEncodeChainIds.join(',') : 'none'}.`
|
||||
+ ` Post-Encode-Scripte: ${selectedPostEncodeScripts.length > 0 ? selectedPostEncodeScripts.map((item) => item.name).join(' -> ') : 'none'}.`
|
||||
+ ` Post-Encode-Ketten: ${selectedPostEncodeChainIds.length > 0 ? selectedPostEncodeChainIds.join(',') : 'none'}.`
|
||||
+ (resolvedUserPreset ? ` User-Preset: "${resolvedUserPreset.name}" (ID ${resolvedUserPreset.id}).` : '')
|
||||
);
|
||||
|
||||
if (!skipPipelineStateUpdate) {
|
||||
@@ -6683,7 +6708,8 @@ class PipelineService extends EventEmitter {
|
||||
trackSelection,
|
||||
titleId: handBrakeTitleId,
|
||||
mediaProfile,
|
||||
settingsMap: settings
|
||||
settingsMap: settings,
|
||||
userPreset: encodePlan?.userPreset || null
|
||||
});
|
||||
if (trackSelection) {
|
||||
await historyService.appendLog(
|
||||
|
||||
@@ -847,10 +847,20 @@ class SettingsService {
|
||||
if (selectedTitleId !== null) {
|
||||
baseArgs.push('-t', String(selectedTitleId));
|
||||
}
|
||||
if (map.handbrake_preset) {
|
||||
baseArgs.push('-Z', map.handbrake_preset);
|
||||
|
||||
// User preset overrides settings-derived preset and extra args
|
||||
const userPreset = options?.userPreset || null;
|
||||
const effectiveHandbrakePreset = userPreset !== null
|
||||
? (userPreset.handbrakePreset || null)
|
||||
: (map.handbrake_preset || null);
|
||||
const effectiveExtraArgs = userPreset !== null
|
||||
? (userPreset.extraArgs || '')
|
||||
: (map.handbrake_extra_args || '');
|
||||
|
||||
if (effectiveHandbrakePreset) {
|
||||
baseArgs.push('-Z', effectiveHandbrakePreset);
|
||||
}
|
||||
const extra = splitArgs(map.handbrake_extra_args);
|
||||
const extra = splitArgs(effectiveExtraArgs);
|
||||
const rawSelection = options?.trackSelection || null;
|
||||
const hasSelection = rawSelection && typeof rawSelection === 'object';
|
||||
|
||||
@@ -860,7 +870,8 @@ class SettingsService {
|
||||
args: [...baseArgs, ...extra],
|
||||
inputFile,
|
||||
outputFile,
|
||||
selectedTitleId
|
||||
selectedTitleId,
|
||||
userPresetId: userPreset?.id || null
|
||||
});
|
||||
return { cmd, args: [...baseArgs, ...extra] };
|
||||
}
|
||||
|
||||
133
backend/src/services/userPresetService.js
Normal file
133
backend/src/services/userPresetService.js
Normal file
@@ -0,0 +1,133 @@
|
||||
const { getDb } = require('../db/database');
|
||||
const logger = require('./logger').child('USER_PRESET');
|
||||
|
||||
const VALID_MEDIA_TYPES = new Set(['bluray', 'dvd', 'other', 'all']);
|
||||
|
||||
function normalizeMediaType(value) {
|
||||
const v = String(value || '').trim().toLowerCase();
|
||||
return VALID_MEDIA_TYPES.has(v) ? v : 'all';
|
||||
}
|
||||
|
||||
function rowToPreset(row) {
|
||||
if (!row) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
mediaType: row.media_type,
|
||||
handbrakePreset: row.handbrake_preset || null,
|
||||
extraArgs: row.extra_args || null,
|
||||
description: row.description || null,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at
|
||||
};
|
||||
}
|
||||
|
||||
async function listPresets(mediaType = null) {
|
||||
const db = await getDb();
|
||||
let rows;
|
||||
if (mediaType && VALID_MEDIA_TYPES.has(mediaType)) {
|
||||
rows = await db.all(
|
||||
`SELECT * FROM user_presets WHERE media_type = ? OR media_type = 'all' ORDER BY name ASC`,
|
||||
[mediaType]
|
||||
);
|
||||
} else {
|
||||
rows = await db.all(`SELECT * FROM user_presets ORDER BY media_type ASC, name ASC`);
|
||||
}
|
||||
return rows.map(rowToPreset);
|
||||
}
|
||||
|
||||
async function getPresetById(id) {
|
||||
const db = await getDb();
|
||||
const row = await db.get(`SELECT * FROM user_presets WHERE id = ? LIMIT 1`, [id]);
|
||||
return rowToPreset(row);
|
||||
}
|
||||
|
||||
async function createPreset(payload) {
|
||||
const name = String(payload?.name || '').trim();
|
||||
if (!name) {
|
||||
const error = new Error('Preset-Name darf nicht leer sein.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const mediaType = normalizeMediaType(payload?.mediaType);
|
||||
const handbrakePreset = String(payload?.handbrakePreset || '').trim() || null;
|
||||
const extraArgs = String(payload?.extraArgs || '').trim() || null;
|
||||
const description = String(payload?.description || '').trim() || null;
|
||||
|
||||
const db = await getDb();
|
||||
const result = await db.run(
|
||||
`INSERT INTO user_presets (name, media_type, handbrake_preset, extra_args, description)
|
||||
VALUES (?, ?, ?, ?, ?)`,
|
||||
[name, mediaType, handbrakePreset, extraArgs, description]
|
||||
);
|
||||
|
||||
const preset = await getPresetById(result.lastID);
|
||||
logger.info('create', { id: preset.id, name: preset.name, mediaType: preset.mediaType });
|
||||
return preset;
|
||||
}
|
||||
|
||||
async function updatePreset(id, payload) {
|
||||
const db = await getDb();
|
||||
const existing = await getPresetById(id);
|
||||
if (!existing) {
|
||||
const error = new Error(`Preset ${id} nicht gefunden.`);
|
||||
error.statusCode = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const name = payload?.name !== undefined ? String(payload.name || '').trim() : existing.name;
|
||||
if (!name) {
|
||||
const error = new Error('Preset-Name darf nicht leer sein.');
|
||||
error.statusCode = 400;
|
||||
throw error;
|
||||
}
|
||||
|
||||
const mediaType = payload?.mediaType !== undefined
|
||||
? normalizeMediaType(payload.mediaType)
|
||||
: existing.mediaType;
|
||||
const handbrakePreset = payload?.handbrakePreset !== undefined
|
||||
? (String(payload.handbrakePreset || '').trim() || null)
|
||||
: existing.handbrakePreset;
|
||||
const extraArgs = payload?.extraArgs !== undefined
|
||||
? (String(payload.extraArgs || '').trim() || null)
|
||||
: existing.extraArgs;
|
||||
const description = payload?.description !== undefined
|
||||
? (String(payload.description || '').trim() || null)
|
||||
: existing.description;
|
||||
|
||||
await db.run(
|
||||
`UPDATE user_presets
|
||||
SET name = ?, media_type = ?, handbrake_preset = ?, extra_args = ?, description = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?`,
|
||||
[name, mediaType, handbrakePreset, extraArgs, description, id]
|
||||
);
|
||||
|
||||
const updated = await getPresetById(id);
|
||||
logger.info('update', { id: updated.id, name: updated.name });
|
||||
return updated;
|
||||
}
|
||||
|
||||
async function deletePreset(id) {
|
||||
const db = await getDb();
|
||||
const existing = await getPresetById(id);
|
||||
if (!existing) {
|
||||
const error = new Error(`Preset ${id} nicht gefunden.`);
|
||||
error.statusCode = 404;
|
||||
throw error;
|
||||
}
|
||||
|
||||
await db.run(`DELETE FROM user_presets WHERE id = ?`, [id]);
|
||||
logger.info('delete', { id: existing.id, name: existing.name });
|
||||
return existing;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listPresets,
|
||||
getPresetById,
|
||||
createPreset,
|
||||
updatePreset,
|
||||
deletePreset
|
||||
};
|
||||
Reference in New Issue
Block a user