Fix: direct .gves→hires lookup, add /hires-media mount, debug logging
- Added /mnt/Hitchcock/bmg_video/Media as read-only bind mount at /hires-media in container - Added direct .gves→hires fallback that works even when proxyLinks is empty - For each .gves block, searches unlinked high-res proxy block titles against media folder - Added console logging to trace the lookup process for debugging - This handles the case where FramelightX creates no explicit linkages at all
This commit is contained in:
parent
c29245758c
commit
36e104ebdd
2 changed files with 76 additions and 34 deletions
|
|
@ -38,6 +38,8 @@ services:
|
||||||
- /mnt/smb-ame/Watch:/watch
|
- /mnt/smb-ame/Watch:/watch
|
||||||
- /mnt/smb-ame/Output:/output
|
- /mnt/smb-ame/Output:/output
|
||||||
- /mnt/smb-ame/Logs:/ame-logs
|
- /mnt/smb-ame/Logs:/ame-logs
|
||||||
|
# High-res media folder for fallback lookup
|
||||||
|
- /mnt/Hitchcock/bmg_video/Media:/hires-media:ro
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
app_data:
|
app_data:
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,8 @@ function parseProxyLinks(xml, mediaBlocks) {
|
||||||
function findHighResFileForGves(gvesPath, hiresTitle, hiresMediaFolder, fs) {
|
function findHighResFileForGves(gvesPath, hiresTitle, hiresMediaFolder, fs) {
|
||||||
if (!hiresMediaFolder) return null;
|
if (!hiresMediaFolder) return null;
|
||||||
|
|
||||||
|
console.log(`[HIRES LOOKUP] Searching for title="${hiresTitle}" in folder="${hiresMediaFolder}"`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Normalize the folder path
|
// Normalize the folder path
|
||||||
const searchFolder = hiresMediaFolder.replace(/\\/g, '/').replace(/\/$/, '');
|
const searchFolder = hiresMediaFolder.replace(/\\/g, '/').replace(/\/$/, '');
|
||||||
|
|
@ -266,6 +268,7 @@ function findHighResFileForGves(gvesPath, hiresTitle, hiresMediaFolder, fs) {
|
||||||
// Match if filename contains the title
|
// Match if filename contains the title
|
||||||
if (fileLower.includes(titleLower)) {
|
if (fileLower.includes(titleLower)) {
|
||||||
const fullPath = `${searchFolder}/${file}`;
|
const fullPath = `${searchFolder}/${file}`;
|
||||||
|
console.log(`[HIRES LOOKUP] MATCH FOUND: "${file}" contains "${hiresTitle}"`);
|
||||||
return fullPath.replace(/\//g, '\\');
|
return fullPath.replace(/\//g, '\\');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -406,56 +409,93 @@ function performSwaps(xml, mediaBlocks, proxyLinks, options = {}) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle unlinked high-res proxy blocks (have IsProxy: true, FilePath: null, no proxyLinks entry)
|
// ─── Direct .gves → high-res lookup (when proxyLinks is empty) ───
|
||||||
// These occur when FramelightX created proxy blocks but didn't link them explicitly
|
// When FramelightX doesn't create explicit proxy linkages, we need to
|
||||||
if (options.hiresMediaFolder && allGvesBlocks.length > 0) {
|
// directly find high-res files for each .gves block in the media folder.
|
||||||
// Get the first .gves block as reference (for path lookup)
|
if (options.hiresMediaFolder) {
|
||||||
const gvesRef = allGvesBlocks[0].block;
|
const processedGves = new Set(gvesUids); // Already handled above
|
||||||
|
|
||||||
for (const [uid, hiresBlock] of Object.entries(mediaBlocks)) {
|
for (const { uid: gvesUid, block: gvesBlock } of allGvesBlocks) {
|
||||||
// Skip if already processed, not a proxy, or already has a path
|
if (processedGves.has(gvesUid)) continue;
|
||||||
if (gvesUids.includes(uid) || !hiresBlock.isProxy || hiresBlock.filePath) continue;
|
|
||||||
|
|
||||||
// Try to find a high-res file for this unlinked proxy using its Title
|
// Extract the .gves filename to use as a lookup key
|
||||||
|
const gvesFilename = gvesBlock.filePath.split('\\').pop().split('/').pop();
|
||||||
|
const gvesBaseName = gvesFilename.replace(/\.[^.]+$/, '');
|
||||||
|
|
||||||
|
// Try to find a matching high-res file using the .gves block's title
|
||||||
|
// or by searching the high-res media folder
|
||||||
let hiresPath = findHighResFileForGves(
|
let hiresPath = findHighResFileForGves(
|
||||||
gvesRef.filePath, // Use first gves path for reference
|
gvesBlock.filePath,
|
||||||
hiresBlock.title,
|
gvesBlock.title,
|
||||||
options.hiresMediaFolder,
|
options.hiresMediaFolder,
|
||||||
fs
|
fs
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Also try matching against unlinked high-res proxy blocks' titles
|
||||||
|
if (!hiresPath) {
|
||||||
|
for (const [huid, hblock] of Object.entries(mediaBlocks)) {
|
||||||
|
if (!hblock.isProxy || hblock.filePath) continue;
|
||||||
|
hiresPath = findHighResFileForGves(
|
||||||
|
gvesBlock.filePath,
|
||||||
|
hblock.title,
|
||||||
|
options.hiresMediaFolder,
|
||||||
|
fs
|
||||||
|
);
|
||||||
|
if (hiresPath) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!hiresPath) continue;
|
if (!hiresPath) continue;
|
||||||
|
|
||||||
const hiresTitle = hiresBlock.title || pathToTitle(hiresPath);
|
const hiresTitle = pathToTitle(hiresPath);
|
||||||
|
const gvesPath = gvesBlock.filePath;
|
||||||
|
const gvesPathEscaped = escapeRegex(gvesPath);
|
||||||
|
|
||||||
// Perform replacements for this unlinked proxy
|
console.log(`[FALLBACK SWAP] ${gvesPath} → ${hiresPath}`);
|
||||||
// We'll replace the Title in the XML with the found file
|
|
||||||
if (hiresBlock.title) {
|
swaps.push({
|
||||||
const titleEscaped = escapeRegex(hiresBlock.title);
|
gvesUid,
|
||||||
|
hiresUid: 'direct-lookup',
|
||||||
|
oldPath: gvesPath,
|
||||||
|
newPath: hiresPath,
|
||||||
|
newTitle: hiresTitle
|
||||||
|
});
|
||||||
|
|
||||||
|
// Replace FilePath tags
|
||||||
remappedXml = remappedXml.replace(
|
remappedXml = remappedXml.replace(
|
||||||
new RegExp(`<Title>${titleEscaped}</Title>`, 'g'),
|
new RegExp(`<FilePath>${gvesPathEscaped}</FilePath>`, 'g'),
|
||||||
|
`<FilePath>${hiresPath}</FilePath>`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Replace ActualMediaFilePath tags
|
||||||
|
remappedXml = remappedXml.replace(
|
||||||
|
new RegExp(`<ActualMediaFilePath>${gvesPathEscaped}</ActualMediaFilePath>`, 'g'),
|
||||||
|
`<ActualMediaFilePath>${hiresPath}</ActualMediaFilePath>`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Replace RelativePath tags
|
||||||
|
if (gvesBlock.relativePath) {
|
||||||
|
const relPathEscaped = escapeRegex(gvesBlock.relativePath);
|
||||||
|
remappedXml = remappedXml.replace(
|
||||||
|
new RegExp(`<RelativePath>${relPathEscaped}</RelativePath>`, 'g'),
|
||||||
|
`<RelativePath>${hiresPath}</RelativePath>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace Title tags that match the .gves filename
|
||||||
|
if (gvesFilename) {
|
||||||
|
const gvesTitleEscaped = escapeRegex(gvesFilename);
|
||||||
|
remappedXml = remappedXml.replace(
|
||||||
|
new RegExp(`<Title>${gvesTitleEscaped}</Title>`, 'g'),
|
||||||
`<Title>${hiresTitle}</Title>`
|
`<Title>${hiresTitle}</Title>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a FilePath to the high-res block's Media section
|
// Replace ImplementationID
|
||||||
// Look for the Media block with this Title and add FilePath if missing
|
remappedXml = remappedXml.replace(
|
||||||
const mediaBlockRegex = new RegExp(
|
new RegExp(`<ImplementationID>${escapeRegex(FRAMELIGHTX_IMPL_ID)}</ImplementationID>`, 'g'),
|
||||||
`<Media[^>]*>([^<]*<Title>${escapeRegex(hiresBlock.title)}</Title>[^<]*)</Media>`,
|
`<ImplementationID>${NULL_IMPL_ID}</ImplementationID>`
|
||||||
'g'
|
|
||||||
);
|
);
|
||||||
remappedXml = remappedXml.replace(mediaBlockRegex, (match) => {
|
|
||||||
if (match.includes('<FilePath>')) return match; // Already has path
|
|
||||||
return match.replace(`</Media>`, `<FilePath>${hiresPath}</FilePath></Media>`);
|
|
||||||
});
|
|
||||||
|
|
||||||
swaps.push({
|
|
||||||
gvesUid: 'unlinked',
|
|
||||||
hiresUid: uid,
|
|
||||||
oldPath: 'null',
|
|
||||||
newPath: hiresPath,
|
|
||||||
newTitle: hiresTitle
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue