diff --git a/backend/src/services/pipelineService.js b/backend/src/services/pipelineService.js index fe23166..e995533 100644 --- a/backend/src/services/pipelineService.js +++ b/backend/src/services/pipelineService.js @@ -12010,6 +12010,7 @@ class PipelineService extends EventEmitter { const reviewPlugin = await this.resolveAnalyzePlugin({ mediaProfile }, 'review').catch(() => null); let reviewPluginExecution = null; const analyzeContext = mkInfo?.analyzeContext || {}; + let effectiveAnalyzeContext = analyzeContext; const playlistAnalysis = analyzeContext.playlistAnalysis || this.snapshot.context?.playlistAnalysis || null; const selectedPlaylistId = normalizePlaylistId( options?.selectedPlaylist @@ -12024,7 +12025,7 @@ class PipelineService extends EventEmitter { ?? null; const selectedMakemkvTitleId = normalizeNonNegativeInteger(selectedMakemkvTitleIdRaw); const selectedMetadata = resolveSelectedMetadataForJob(job, analyzeContext, this.snapshot.context || {}); - const isSeriesDvdReview = isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, analyzeContext); + let effectiveIsSeriesDvdReview = isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, analyzeContext); await this.setState('MEDIAINFO_CHECK', { activeJobId: jobId, @@ -12076,7 +12077,13 @@ class PipelineService extends EventEmitter { error.runInfo = runInfo; throw error; } - if (isSeriesDvdReview) { + if (normalizeMediaProfile(mediaProfile) === 'dvd') { + const seriesScanContextResult = enrichSeriesAnalyzeContextFromScan(effectiveAnalyzeContext, lines); + effectiveAnalyzeContext = seriesScanContextResult.analyzeContext; + effectiveIsSeriesDvdReview = isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, effectiveAnalyzeContext); + } + + if (effectiveIsSeriesDvdReview) { await historyService.appendLog( jobId, 'SYSTEM', @@ -12092,7 +12099,7 @@ class PipelineService extends EventEmitter { selectedMakemkvTitleId, mediaProfile, sourceArg, - disableMinLengthFilter: isSeriesDvdReview + disableMinLengthFilter: effectiveIsSeriesDvdReview }); if (!Array.isArray(review.titles) || review.titles.length === 0) { @@ -12110,6 +12117,10 @@ class PipelineService extends EventEmitter { status: 'READY_TO_ENCODE', last_state: 'READY_TO_ENCODE', error_message: null, + makemkv_info_json: JSON.stringify(this.withAnalyzeContextMediaProfile({ + ...(mkInfo && typeof mkInfo === 'object' ? mkInfo : {}), + analyzeContext: effectiveAnalyzeContext + }, mediaProfile)), mediainfo_info_json: JSON.stringify(persistedMediainfoInfo), encode_plan_json: JSON.stringify(review), encode_input_path: review.encodeInputPath || null, @@ -15604,15 +15615,15 @@ class PipelineService extends EventEmitter { const isConverterReview = String(options?.mode || '').trim().toLowerCase() === 'converter' || String(mediaProfile || '').trim().toLowerCase() === 'converter'; const selectedMetadata = resolveSelectedMetadataForJob(job, analyzeContext, this.snapshot.context || {}); - const isSeriesDvdReview = isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, analyzeContext); - const reviewSettings = isConverterReview + let effectiveIsSeriesDvdReview = isSeriesDvdMetadataSelection(mediaProfile, selectedMetadata, analyzeContext); + let reviewSettings = isConverterReview ? { ...settings, makemkv_min_length_minutes: 0, handbrake_preset: '', handbrake_extra_args: '' } - : (isSeriesDvdReview + : (effectiveIsSeriesDvdReview ? { ...settings, makemkv_min_length_minutes: 0 @@ -15640,7 +15651,7 @@ class PipelineService extends EventEmitter { }; } - if (isSeriesDvdReview) { + if (effectiveIsSeriesDvdReview) { await historyService.appendLog( jobId, 'SYSTEM', @@ -15748,16 +15759,26 @@ class PipelineService extends EventEmitter { dvdHandBrakeScanJson = parseMediainfoJsonOutput(dvdScanLines.join('\n')); if (dvdHandBrakeScanJson) { - const minLengthMinutes = Number(reviewSettings?.makemkv_min_length_minutes || 0); - const minLengthSeconds = Math.max(0, Math.round(minLengthMinutes * 60)); const allDvdTitles = parseHandBrakeTitleList(dvdHandBrakeScanJson); - const filteredDvdCandidatesRaw = minLengthSeconds > 0 - ? allDvdTitles.filter((t) => t.durationSeconds >= minLengthSeconds) - : allDvdTitles; - const seriesScanContextResult = isSeriesDvdReview - ? enrichSeriesAnalyzeContextFromScan(effectiveAnalyzeContext, dvdScanLines) - : { analyzeContext: effectiveAnalyzeContext, derived: false, reason: 'not_series' }; + const seriesScanContextResult = enrichSeriesAnalyzeContextFromScan(effectiveAnalyzeContext, dvdScanLines); effectiveAnalyzeContext = seriesScanContextResult.analyzeContext; + const wasSeriesDvdReview = effectiveIsSeriesDvdReview; + effectiveIsSeriesDvdReview = isSeriesDvdMetadataSelection( + mediaProfile, + selectedMetadata, + effectiveAnalyzeContext + ); + if (effectiveIsSeriesDvdReview && !wasSeriesDvdReview) { + reviewSettings = { + ...reviewSettings, + makemkv_min_length_minutes: 0 + }; + await historyService.appendLog( + jobId, + 'SYSTEM', + 'Serien-DVD nachträglich im HandBrake-Scan erkannt: Mindestlängen-Filter für Titelprüfung wurde deaktiviert.' + ); + } if (seriesScanContextResult.derived) { await historyService.appendLog( jobId, @@ -15765,6 +15786,11 @@ class PipelineService extends EventEmitter { 'Serien-Titelklassifizierung aus HandBrake-Scan aktualisiert (PlayAll/Kurz/Duplikate markiert).' ); } + const minLengthMinutes = Number(reviewSettings?.makemkv_min_length_minutes || 0); + const minLengthSeconds = Math.max(0, Math.round(minLengthMinutes * 60)); + const filteredDvdCandidatesRaw = minLengthSeconds > 0 + ? allDvdTitles.filter((t) => t.durationSeconds >= minLengthSeconds) + : allDvdTitles; const filteredSeriesResult = filterSeriesDvdHandBrakeCandidates(filteredDvdCandidatesRaw, effectiveAnalyzeContext); const filteredDvdCandidates = filteredSeriesResult.candidates; const minLengthLabel = minLengthSeconds > 0 @@ -16088,7 +16114,7 @@ class PipelineService extends EventEmitter { `HandBrake DVD Titel automatisch gewählt (aus Scan): -t ${dvdSelectedTitleInfo.handBrakeTitleId}` ); } else if (dvdScannedCandidates && dvdScannedCandidates.length > 0) { - if (isSeriesDvdReview) { + if (effectiveIsSeriesDvdReview) { const seriesTitleIds = normalizeReviewTitleIdList( dvdScannedCandidates.map((item) => item?.handBrakeTitleId) ); @@ -16156,6 +16182,10 @@ class PipelineService extends EventEmitter { status: 'WAITING_FOR_USER_DECISION', last_state: 'WAITING_FOR_USER_DECISION', error_message: null, + makemkv_info_json: JSON.stringify(this.withAnalyzeContextMediaProfile({ + ...(mkInfo && typeof mkInfo === 'object' ? mkInfo : {}), + analyzeContext: effectiveAnalyzeContext + }, mediaProfile)), mediainfo_info_json: JSON.stringify(waitingMediainfoInfo), encode_plan_json: JSON.stringify(enrichedReview), encode_input_path: null, @@ -16229,13 +16259,25 @@ class PipelineService extends EventEmitter { dvdTitleScanJson = parseMediainfoJsonOutput(dvdTitleScanLines.join('\n')); if (dvdTitleScanJson) { const allTitles = parseHandBrakeTitleList(dvdTitleScanJson); - const minLengthMinutes = Number(reviewSettings?.makemkv_min_length_minutes || 0); - const minLengthSeconds = Math.max(0, Math.round(minLengthMinutes * 60)); - const titleCandidatesRaw = allTitles.filter((t) => t.durationSeconds >= minLengthSeconds); - const seriesScanContextResult = isSeriesDvdReview - ? enrichSeriesAnalyzeContextFromScan(effectiveAnalyzeContext, dvdTitleScanLines) - : { analyzeContext: effectiveAnalyzeContext, derived: false, reason: 'not_series' }; + const seriesScanContextResult = enrichSeriesAnalyzeContextFromScan(effectiveAnalyzeContext, dvdTitleScanLines); effectiveAnalyzeContext = seriesScanContextResult.analyzeContext; + const wasSeriesDvdReview = effectiveIsSeriesDvdReview; + effectiveIsSeriesDvdReview = isSeriesDvdMetadataSelection( + mediaProfile, + selectedMetadata, + effectiveAnalyzeContext + ); + if (effectiveIsSeriesDvdReview && !wasSeriesDvdReview) { + reviewSettings = { + ...reviewSettings, + makemkv_min_length_minutes: 0 + }; + await historyService.appendLog( + jobId, + 'SYSTEM', + 'Serien-DVD nachträglich im HandBrake-Titelscan erkannt: Mindestlängen-Filter für Titelprüfung wurde deaktiviert.' + ); + } if (seriesScanContextResult.derived) { await historyService.appendLog( jobId, @@ -16243,6 +16285,9 @@ class PipelineService extends EventEmitter { 'Serien-Titelklassifizierung aus HandBrake-Titelscan aktualisiert (PlayAll/Kurz/Duplikate markiert).' ); } + const minLengthMinutes = Number(reviewSettings?.makemkv_min_length_minutes || 0); + const minLengthSeconds = Math.max(0, Math.round(minLengthMinutes * 60)); + const titleCandidatesRaw = allTitles.filter((t) => t.durationSeconds >= minLengthSeconds); const filteredSeriesResult = filterSeriesDvdHandBrakeCandidates(titleCandidatesRaw, effectiveAnalyzeContext); const titleCandidates = filteredSeriesResult.candidates; const minLengthLabel = minLengthSeconds > 0 @@ -16273,7 +16318,7 @@ class PipelineService extends EventEmitter { `HandBrake DVD Titel automatisch gewählt: -t ${titleCandidates[0].handBrakeTitleId}` ); } else if (titleCandidates.length > 1) { - if (isSeriesDvdReview) { + if (effectiveIsSeriesDvdReview) { const seriesTitleIds = normalizeReviewTitleIdList( titleCandidates.map((item) => item?.handBrakeTitleId) ); @@ -16339,6 +16384,10 @@ class PipelineService extends EventEmitter { status: 'WAITING_FOR_USER_DECISION', last_state: 'WAITING_FOR_USER_DECISION', error_message: null, + makemkv_info_json: JSON.stringify(this.withAnalyzeContextMediaProfile({ + ...(mkInfo && typeof mkInfo === 'object' ? mkInfo : {}), + analyzeContext: effectiveAnalyzeContext + }, mediaProfile)), mediainfo_info_json: JSON.stringify(waitingMediainfoInfo), encode_plan_json: JSON.stringify(enrichedReview), encode_input_path: null, @@ -16421,6 +16470,10 @@ class PipelineService extends EventEmitter { status: 'READY_TO_ENCODE', last_state: 'READY_TO_ENCODE', error_message: null, + makemkv_info_json: JSON.stringify(this.withAnalyzeContextMediaProfile({ + ...(mkInfo && typeof mkInfo === 'object' ? mkInfo : {}), + analyzeContext: effectiveAnalyzeContext + }, mediaProfile)), mediainfo_info_json: JSON.stringify(persistedMediainfoInfo), encode_plan_json: JSON.stringify(enrichedReview), encode_input_path: enrichedReview.encodeInputPath || null,