0.10.2-13 DVD Media Info Fix
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"dependencies": {
|
||||
"archiver": "^7.0.1",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-backend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"private": true,
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
|
||||
@@ -8154,8 +8154,10 @@ class PipelineService extends EventEmitter {
|
||||
|
||||
const mediaInfoByPath = {};
|
||||
const mediaInfoRuns = [];
|
||||
let effectiveMediaFiles = mediaFiles;
|
||||
|
||||
const buildReviewSnapshot = (processedCount) => {
|
||||
const processedFiles = mediaFiles
|
||||
const processedFiles = effectiveMediaFiles
|
||||
.slice(0, processedCount)
|
||||
.filter((item) => Boolean(mediaInfoByPath[item.path]));
|
||||
|
||||
@@ -8178,12 +8180,113 @@ class PipelineService extends EventEmitter {
|
||||
mediaProfile,
|
||||
sourceJobId: options.sourceJobId || null,
|
||||
reviewConfirmed: false,
|
||||
partial: processedFiles.length < mediaFiles.length,
|
||||
partial: processedFiles.length < effectiveMediaFiles.length,
|
||||
processedFiles: processedFiles.length,
|
||||
totalFiles: mediaFiles.length
|
||||
totalFiles: effectiveMediaFiles.length
|
||||
};
|
||||
};
|
||||
|
||||
// For DVD sources, use HandBrake scan directly instead of mediainfo (mediainfo
|
||||
// is unreliable on VOB files and often returns incomplete track information).
|
||||
const isDvdSource = rawMedia.source === 'dvd'
|
||||
|| rawMedia.source === 'dvd_image'
|
||||
|| rawMedia.source === 'single_extensionless';
|
||||
let dvdHandBrakeScanJson = null;
|
||||
let dvdHandBrakeScanInputPath = null;
|
||||
|
||||
if (isDvdSource && mediaFiles.length > 0) {
|
||||
// For 'dvd': scan the folder that contains VIDEO_TS (parent of the VIDEO_TS dir).
|
||||
// For image/extensionless: scan the file directly.
|
||||
dvdHandBrakeScanInputPath = rawMedia.source === 'dvd'
|
||||
? path.dirname(path.dirname(mediaFiles[0].path))
|
||||
: mediaFiles[0].path;
|
||||
|
||||
await historyService.appendLog(
|
||||
jobId,
|
||||
'SYSTEM',
|
||||
`DVD-Analyse via HandBrake Scan: ${path.basename(dvdHandBrakeScanInputPath)}`
|
||||
);
|
||||
await this.updateProgress('MEDIAINFO_CHECK', 10, null, 'HandBrake DVD-Scan läuft', jobId);
|
||||
|
||||
const dvdScanLines = [];
|
||||
const dvdScanConfig = await settingsService.buildHandBrakeScanConfigForInput(dvdHandBrakeScanInputPath, {
|
||||
mediaProfile,
|
||||
settingsMap: settings
|
||||
});
|
||||
logger.info('mediainfo:review:dvd-handbrake-scan:command', {
|
||||
jobId,
|
||||
dvdHandBrakeScanInputPath,
|
||||
cmd: dvdScanConfig.cmd,
|
||||
args: dvdScanConfig.args
|
||||
});
|
||||
|
||||
const dvdScanRunInfo = await this.runCommand({
|
||||
jobId,
|
||||
stage: 'MEDIAINFO_CHECK',
|
||||
source: 'HANDBRAKE_SCAN_DVD',
|
||||
cmd: dvdScanConfig.cmd,
|
||||
args: dvdScanConfig.args,
|
||||
collectLines: dvdScanLines,
|
||||
collectStderrLines: false
|
||||
});
|
||||
|
||||
dvdHandBrakeScanJson = parseMediainfoJsonOutput(dvdScanLines.join('\n'));
|
||||
if (dvdHandBrakeScanJson) {
|
||||
const titleInfo = parseHandBrakeSelectedTitleInfo(dvdHandBrakeScanJson);
|
||||
if (titleInfo) {
|
||||
const syntheticMediaInfo = buildSyntheticMediaInfoFromMakeMkvTitle(titleInfo);
|
||||
mediaInfoByPath[dvdHandBrakeScanInputPath] = syntheticMediaInfo;
|
||||
effectiveMediaFiles = [{ path: dvdHandBrakeScanInputPath, size: 0 }];
|
||||
const audioCount = Array.isArray(titleInfo.audioTracks) ? titleInfo.audioTracks.length : 0;
|
||||
const subtitleCount = Array.isArray(titleInfo.subtitleTracks) ? titleInfo.subtitleTracks.length : 0;
|
||||
await historyService.appendLog(
|
||||
jobId,
|
||||
'SYSTEM',
|
||||
`HandBrake DVD-Scan: Audio=${audioCount}, Subtitle=${subtitleCount}, Dauer=${formatDurationClock(titleInfo.durationSeconds)}`
|
||||
);
|
||||
} else {
|
||||
await historyService.appendLog(
|
||||
jobId,
|
||||
'SYSTEM',
|
||||
'HandBrake DVD-Scan: Kein Titel erkannt, falle auf MediaInfo zurück.'
|
||||
);
|
||||
dvdHandBrakeScanJson = null;
|
||||
}
|
||||
} else {
|
||||
await historyService.appendLog(
|
||||
jobId,
|
||||
'SYSTEM',
|
||||
'HandBrake DVD-Scan: Ausgabe nicht lesbar, falle auf MediaInfo zurück.'
|
||||
);
|
||||
}
|
||||
|
||||
mediaInfoRuns.push({ filePath: dvdHandBrakeScanInputPath, runInfo: dvdScanRunInfo, fallbackRunInfo: null });
|
||||
|
||||
const partialReview = buildReviewSnapshot(1);
|
||||
if (this.isPrimaryJob(jobId)) {
|
||||
await this.setState('MEDIAINFO_CHECK', {
|
||||
activeJobId: jobId,
|
||||
progress: 50,
|
||||
eta: null,
|
||||
statusText: `HandBrake DVD-Scan abgeschlossen: ${path.basename(dvdHandBrakeScanInputPath)}`,
|
||||
context: {
|
||||
jobId,
|
||||
rawPath,
|
||||
inputPath: partialReview?.encodeInputPath || null,
|
||||
hasEncodableTitle: Boolean(partialReview?.encodeInputPath),
|
||||
reviewConfirmed: false,
|
||||
mode: options.mode || 'rip',
|
||||
mediaProfile,
|
||||
sourceJobId: options.sourceJobId || null,
|
||||
mediaInfoReview: partialReview,
|
||||
selectedMetadata
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// For non-DVD sources (or when HandBrake scan failed), run mediainfo on each file.
|
||||
if (!isDvdSource || !dvdHandBrakeScanJson) {
|
||||
for (let i = 0; i < mediaFiles.length; i += 1) {
|
||||
const file = mediaFiles[i];
|
||||
const percent = Number((((i + 1) / mediaFiles.length) * 100).toFixed(2));
|
||||
@@ -8260,9 +8363,10 @@ class PipelineService extends EventEmitter {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const review = buildMediainfoReview({
|
||||
mediaFiles,
|
||||
mediaFiles: effectiveMediaFiles,
|
||||
mediaInfoByPath,
|
||||
settings,
|
||||
presetProfile,
|
||||
@@ -8279,8 +8383,8 @@ class PipelineService extends EventEmitter {
|
||||
sourceJobId: options.sourceJobId || null,
|
||||
reviewConfirmed: false,
|
||||
partial: false,
|
||||
processedFiles: mediaFiles.length,
|
||||
totalFiles: mediaFiles.length
|
||||
processedFiles: effectiveMediaFiles.length,
|
||||
totalFiles: effectiveMediaFiles.length
|
||||
};
|
||||
const reviewPrefillResult = applyPreviousSelectionDefaultsToReviewPlan(
|
||||
enrichedReview,
|
||||
@@ -8295,7 +8399,10 @@ class PipelineService extends EventEmitter {
|
||||
|| rawMedia.source === 'dvd_image'
|
||||
|| rawMedia.source === 'single_extensionless';
|
||||
if (needsHandBrakeTitleScan) {
|
||||
const dvdScanInputPath = rawMedia.source === 'dvd' ? rawPath : mediaFiles[0].path;
|
||||
// Use the same path that was used for the DVD HandBrake scan above, or fall back
|
||||
// to the existing logic for cases where the scan was not yet performed.
|
||||
const dvdScanInputPath = dvdHandBrakeScanInputPath
|
||||
|| (rawMedia.source === 'dvd' ? rawPath : mediaFiles[0].path);
|
||||
const preSelectedHandBrakeTitleId = normalizeReviewTitleId(options?.selectedHandBrakeTitleId);
|
||||
if (preSelectedHandBrakeTitleId) {
|
||||
enrichedReview = {
|
||||
@@ -8309,6 +8416,10 @@ class PipelineService extends EventEmitter {
|
||||
`HandBrake Titel-Auswahl (manuell) übernommen: -t ${preSelectedHandBrakeTitleId}`
|
||||
);
|
||||
} else {
|
||||
// Reuse the HandBrake scan result from the DVD analysis step when available,
|
||||
// otherwise run a fresh scan for title selection.
|
||||
let dvdTitleScanJson = dvdHandBrakeScanJson || null;
|
||||
if (!dvdTitleScanJson) {
|
||||
await historyService.appendLog(
|
||||
jobId,
|
||||
'SYSTEM',
|
||||
@@ -8335,7 +8446,8 @@ class PipelineService extends EventEmitter {
|
||||
collectLines: dvdTitleScanLines,
|
||||
collectStderrLines: false
|
||||
});
|
||||
const dvdTitleScanJson = parseMediainfoJsonOutput(dvdTitleScanLines.join('\n'));
|
||||
dvdTitleScanJson = parseMediainfoJsonOutput(dvdTitleScanLines.join('\n'));
|
||||
}
|
||||
if (dvdTitleScanJson) {
|
||||
const allTitles = parseHandBrakeTitleList(dvdTitleScanJson);
|
||||
const minLengthMinutes = Number(settings?.makemkv_min_length_minutes || 0);
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"dependencies": {
|
||||
"primeicons": "^7.0.0",
|
||||
"primereact": "^10.9.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ripster-frontend",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ripster",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ripster",
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.1.2"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ripster",
|
||||
"private": true,
|
||||
"version": "0.10.2-12",
|
||||
"version": "0.10.2-13",
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
|
||||
"dev:backend": "npm run dev --prefix backend",
|
||||
|
||||
Reference in New Issue
Block a user