Details werden geladen ...
Encode-Konfiguration
Typ: {converterMediaTypeLabel}
Format: {converterOutputFormat ? converterOutputFormat.toUpperCase() : '-'}
Eingabe-Modus: {converterPlan?.isFolder ? 'Ordner' : (converterPlan?.isSharedAudio ? 'Gemeinsam' : 'Einzeln')}
Eingabe-Dateien: {converterInputPaths.length > 0 ? converterInputPaths.length : '-'}
Preset: {converterPresetLabel || '-'}
HandBrake Titel: {converterPlan?.handBrakeTitleId || '-'}
{converterMediaType === 'audio' ? (
Album: {converterMetadata?.albumTitle || job?.title || (job?.id ? `Job #${job.id}` : '-')}
Interpret: {converterMetadata?.albumArtist || '-'}
Jahr: {converterMetadata?.albumYear || job?.year || '-'}
Qualität: {converterAudioQualityLabel || '-'}
) : null}
{converterInputPaths.length > 0 ? (
{converterInputPaths.map((inputPath, index) => (
#{index + 1} | {inputPath}
))}
) : null}
{converterMediaType === 'audio' && converterTrackList.length > 0 ? (
{converterTrackList.map((track, index) => {
const position = Number(track?.position) > 0 ? Math.trunc(Number(track.position)) : (index + 1);
const title = String(track?.title || '').trim() || `Track ${position}`;
const artist = String(track?.artist || '').trim();
return (
#{position} | {artist ? `${artist} - ` : ''}{title}
);
})}
) : null}
) : null}
{!isCd && !isAudiobook && !isConverter && (hasConfiguredSelection || encodePlanUserPreset || job.encodePlan?.minLengthMinutes != null || Array.isArray(job.encodePlan?.titles)) ? (
Encode-Konfiguration
{/* Zeile 1: Preset + Mindestlaufzeit */}
{encodePlanUserPreset ? (
Preset: {encodePlanUserPreset.name || '-'}
) : null}
{job.encodePlan?.minLengthMinutes != null ? (
Mindestlaufzeit: {job.encodePlan.minLengthMinutes} Min.
) : null}
{/* Zeile 2: Skripte */}
{hasConfiguredSelection ? (
Pre-Skripte:{' '}
{configuredSelection.preScripts.length > 0
? configuredSelection.preScripts.join(', ')
: configuredSelection.preChains.length > 0
? configuredSelection.preChains.join(', ')
: '-'}
Post-Skripte:{' '}
{configuredSelection.postScripts.length > 0
? configuredSelection.postScripts.join(', ')
: configuredSelection.postChains.length > 0
? configuredSelection.postChains.join(', ')
: '-'}
) : null}
{/* Spurauswahl – read-only */}
{job.encodePlan && Array.isArray(job.encodePlan.titles) && job.encodePlan.titles.length > 0 ? (
Spurauswahl
{job.encodePlan.titles
.filter((t) => t.selectedForEncode || t.encodeInput || String(t.id) === String(reviewSelectedEncodeTitleId))
.map((title) => {
const audioTracks = Array.isArray(title.audioTracks) ? title.audioTracks : [];
const subtitleTracks = Array.isArray(title.subtitleTracks) ? title.subtitleTracks : [];
return (
#{title.id} | {title.fileName} | {title.durationMinutes != null ? `${Number(title.durationMinutes).toFixed(2)} min` : '-'}
{audioTracks.length > 0 ? (
Tonspuren (Titel #{title.id})
{audioTracks.map((track) => {
const lang = trackLang(track.language || track.languageLabel);
const codec = trackCodec('audio', track.format, track.description || track.title);
const chLayout = trackChLayout(track.channels);
let displayText = `#${track.id} | ${lang} | ${codec}`;
if (chLayout) displayText += ` | ${chLayout}`;
const actionInfo = track.selectedForEncode
? (String(track.encodePreviewSummary || track.encodeActionSummary || '').trim() || 'Copy')
: 'Nicht übernommen';
return (
{displayText}
Encode: {actionInfo}
);
})}
) : null}
{subtitleTracks.length > 0 ? (
Subtitles (Titel #{title.id})
{subtitleTracks.map((track) => {
const lang = trackLang(track.language || track.languageLabel);
const codec = trackCodec('subtitle', track.format);
const displayText = `#${track.id} | ${lang} | ${codec}`;
const rawAction = String(track.subtitlePreviewSummary || track.subtitleActionSummary || '').trim();
const actionInfo = track.selectedForEncode
? (/^nicht übernommen$/i.test(rawAction) ? 'Übernehmen' : (rawAction || 'Übernehmen'))
: 'Nicht übernommen';
return (
{displayText}
Encode: {actionInfo}
);
})}
) : null}
);
})
}
) : null}
) : null}
{(isCd || isAudiobook) && job.encodePlan ? (
{isCd ? 'Titelauswahl' : 'Kapitelauswahl'}
{isCd ? (() => {
const tracksRaw = Array.isArray(job.makemkvInfo?.tracks) && job.makemkvInfo.tracks.length > 0
? job.makemkvInfo.tracks
: (Array.isArray(job.encodePlan?.tracks) ? job.encodePlan.tracks : []);
const selectedSet = Array.isArray(job.encodePlan?.selectedTracks) && job.encodePlan.selectedTracks.length > 0
? new Set(job.encodePlan.selectedTracks.map(Number))
: null;
const encodeResultMap = new Map(
(Array.isArray(job.handbrakeInfo?.tracks) ? job.handbrakeInfo.tracks : [])
.map((r) => [Number(r.position), r])
);
if (tracksRaw.length === 0) return Keine Tracks vorhanden.
;
return (
{tracksRaw.map((track, i) => {
const pos = Number(track.position ?? (i + 1));
const label = String(track.title || track.name || `Track ${pos}`).trim();
const artist = String(track.artist || '').trim() || String(job?.makemkvInfo?.selectedMetadata?.artist || '').trim();
const selected = selectedSet ? selectedSet.has(pos) : track.selected !== false;
const encodeResult = encodeResultMap.get(pos);
const outcome = !selected
? null
: encodeResult
? (encodeResult.success ? 'success' : 'error')
: (job?.ripSuccessful != null ? (job.ripSuccessful ? 'success' : 'error') : null);
return (
#{pos} {artist ? `${artist} - ` : ''}{label}
);
})}
);
})() : (() => {
const audiobookFormat = String(job?.handbrakeInfo?.format || job?.encodePlan?.format || '').trim().toLowerCase();
const isSplitAudiobook = Boolean(audiobookFormat) && audiobookFormat !== 'm4b';
const chapters = Array.isArray(job.handbrakeInfo?.metadata?.chapters) && job.handbrakeInfo.metadata.chapters.length > 0
? job.handbrakeInfo.metadata.chapters
: (Array.isArray(job.makemkvInfo?.chapters) && job.makemkvInfo.chapters.length > 0
? job.makemkvInfo.chapters
: (Array.isArray(job.encodePlan?.metadata?.chapters) ? job.encodePlan.metadata.chapters : []));
const stepsByIndex = new Map(
(Array.isArray(job.handbrakeInfo?.steps) ? job.handbrakeInfo.steps : [])
.map((s) => [Number(s.chapterIndex), s])
);
if (chapters.length === 0) return Keine Kapitelinformationen vorhanden.
;
return (
{chapters.map((chapter, i) => {
const id = Number(chapter.id ?? chapter.index ?? chapter.position ?? (i + 1));
const label = String(chapter.title || chapter.name || `Kapitel ${id}`).trim();
const durationSec = Number(chapter.durationMs || 0) > 0
? Number(chapter.durationMs) / 1000
: Number(chapter.durationSec || 0);
const durLabel = durationSec > 0
? `${Math.floor(durationSec / 60)}:${String(Math.floor(durationSec % 60)).padStart(2, '0')} min`
: '-';
const step = stepsByIndex.get(id);
const stepStatus = step ? String(step.status || '').toUpperCase() : null;
const outcome = stepStatus === 'SUCCESS'
? 'success'
: stepStatus === 'ERROR'
? 'error'
: stepStatus === 'CANCELLED'
? 'cancelled'
: (job?.encodeSuccess != null
? (job.encodeSuccess ? 'success' : (String(job?.status || '').trim().toUpperCase() === 'CANCELLED' ? 'cancelled' : 'error'))
: null);
const encodeLabel = stepStatus === 'SUCCESS' ? 'Erfolgreich'
: stepStatus === 'ERROR' ? 'Fehler'
: stepStatus === 'CANCELLED' ? 'Abgebrochen'
: stepStatus ? stepStatus
: 'Übernommen';
const encodeClass = stepStatus === 'SUCCESS' ? 'tone-ok'
: stepStatus === 'ERROR' ? 'tone-no'
: '';
return (
#{id} | {label} | {durLabel}
{isSplitAudiobook ? (
) : (
Encode: {encodeLabel}
)}
);
})}
);
})()}
Log nicht vorgeladen. Über die Buttons oben laden.
Live-Log wird nur im Ripper während laufender Analyse/Rip/Encode angezeigt.
{showCancelAction ? (
{running ? 'Laufender Job' : 'Wartender Job'}
) : null}
{isCd ? (
Audio CD
) : (
canShowGeneralEncodeActions ? (
Kodierung
{canResumeReady ? (
) : null}
{typeof onRestartEncode === 'function' ? (
) : null}
{typeof onRestartReview === 'function' ? (
) : null}
{typeof onReencode === 'function' ? (
) : null}
) : null
)}
{!isCd && !isAudiobook && !isConverter && typeof onAssignOmdb === 'function' ? (
Metadaten
) : null}
{typeof onDeleteFiles === 'function' ? (
Dateien löschen
) : null}