newtest / static /verify.js
bigbossmonster's picture
Update static/verify.js
ef88f8d verified
document.addEventListener('DOMContentLoaded', () => {
// --- DOM Elements ---
const verifyBtn = document.getElementById('verifyButton');
const loader = document.getElementById('loader');
const progressBar = document.getElementById('progressBar');
const progressPercent = document.getElementById('progressPercent');
const loaderText = document.getElementById('loaderText');
const resultsWrapper = document.getElementById('resultsWrapper');
const resultsArea = document.getElementById('results');
const correctedSrtOutput = document.getElementById('correctedSrtOutput');
const ocrErrorOutput = document.getElementById('ocrErrorOutput');
const errorMessage = document.getElementById('errorMessage');
// Stats
const statChunks = document.getElementById('statChunks');
const statCorrections = document.getElementById('statCorrections');
const statErrors = document.getElementById('statErrors');
const statOcrErrors = document.getElementById('statOcrErrors');
// File Inputs
const pdfUpload = document.getElementById('pdfUpload');
const srtUpload = document.getElementById('srtUpload');
// Global Store for Original SRT Content
let originalSrtContent = "";
// --- Event Listeners ---
if (pdfUpload) {
pdfUpload.addEventListener('change', function() {
if(this.files[0]) document.getElementById('pdfFileName').textContent = this.files[0].name;
});
}
if (srtUpload) {
srtUpload.addEventListener('change', function() {
if(this.files[0]) {
document.getElementById('srtFileName').textContent = this.files[0].name;
// Read content immediately for later patching
const reader = new FileReader();
reader.onload = (e) => { originalSrtContent = e.target.result; };
reader.readAsText(this.files[0]);
}
});
}
if (verifyBtn) {
verifyBtn.addEventListener('click', async () => {
const apiKeys = document.getElementById('apiKeyInput').value.trim();
const pdfFile = pdfUpload ? pdfUpload.files[0] : null;
const srtFile = srtUpload ? srtUpload.files[0] : null;
const pagesPerRequest = document.getElementById('pagesPerRequestInput').value;
const modelName = document.getElementById('modelSelect').value;
if (errorMessage) errorMessage.classList.add('hidden');
if (!apiKeys) return showError("Please enter API Keys.");
if (!pdfFile) return showError("Please upload a PDF.");
if (!srtFile) return showError("Please upload an SRT.");
// Reset UI
verifyBtn.disabled = true;
verifyBtn.classList.add('opacity-50', 'cursor-not-allowed');
if (loader) loader.classList.remove('hidden');
if (resultsWrapper) resultsWrapper.classList.add('hidden');
const formData = new FormData();
formData.append('api_keys', apiKeys);
formData.append('pdf', pdfFile);
formData.append('srt', srtFile);
formData.append('pages_per_request', pagesPerRequest);
formData.append('model_name', modelName);
// Fake Progress
let progress = 0;
const interval = setInterval(() => {
if (progress < 90) {
progress += Math.random() * 5;
if (progress > 90) progress = 90;
if (progressBar) progressBar.style.width = `${progress}%`;
if (progressPercent) progressPercent.textContent = `${Math.round(progress)}%`;
}
}, 800);
try {
const response = await fetch('/verify_batch', {
method: 'POST',
body: formData
});
clearInterval(interval);
const data = await response.json();
if (!response.ok) throw new Error(data.detail || data.error || "Server Error");
if (progressBar) progressBar.style.width = '100%';
if (progressPercent) progressPercent.textContent = '100%';
setTimeout(() => {
if (loader) loader.classList.add('hidden');
displayResults(data);
verifyBtn.disabled = false;
verifyBtn.classList.remove('opacity-50', 'cursor-not-allowed');
}, 500);
} catch (error) {
clearInterval(interval);
if (loader) loader.classList.add('hidden');
verifyBtn.disabled = false;
verifyBtn.classList.remove('opacity-50', 'cursor-not-allowed');
showError(error.message);
}
});
}
// --- Helper Functions ---
function showError(msg) {
if (errorMessage) {
errorMessage.textContent = `Error: ${msg}`;
errorMessage.classList.remove('hidden');
} else {
alert(msg);
}
}
function displayResults(data) {
if (resultsWrapper) resultsWrapper.classList.remove('hidden');
// 1. Stats
if (statChunks) statChunks.textContent = data.total_chunks || 0;
if (statErrors) statErrors.textContent = data.system_errors ? data.system_errors.length : 0;
const corrections = data.corrections || [];
let validCorrections = [];
let ocrReports = "";
// 2. Filter Data
corrections.forEach((item, index) => {
// Only count if it has a correctedSrt field
if (item.correctedSrt) {
validCorrections.push(item);
}
// Collect significant error reports
if (item.errorReport && !item.errorReport.includes("No significant errors")) {
ocrReports += `[Report ${index+1}]\n${item.errorReport}\n\n`;
}
});
if (statCorrections) statCorrections.textContent = validCorrections.length;
if (statOcrErrors) statOcrErrors.textContent = ocrReports ? "!" : "0";
// 3. Fill Textareas
if (resultsArea) resultsArea.value = JSON.stringify(data, null, 2);
if (ocrErrorOutput) ocrErrorOutput.value = ocrReports || "No significant OCR errors reported.";
if (correctedSrtOutput) correctedSrtOutput.value = JSON.stringify(validCorrections, null, 2);
}
// --- ROBUST SRT DOWNLOAD LOGIC ---
const downloadSrtBtn = document.getElementById('downloadSrtBtn');
if (downloadSrtBtn) {
downloadSrtBtn.addEventListener('click', () => {
if (!originalSrtContent) {
alert("Original SRT content is missing. Please re-upload the SRT file to enable patching.");
return;
}
// Parse results from the text area
let corrections = [];
try {
// We use the filtered list we displayed in correctedSrtOutput
corrections = JSON.parse(correctedSrtOutput.value);
} catch (e) {
alert("No valid corrections data found to apply.");
return;
}
if (!corrections || corrections.length === 0) {
alert("There are no corrections to apply.");
return;
}
try {
const patchedSrt = patchSrtFile(originalSrtContent, corrections);
downloadFile(patchedSrt, 'corrected_subtitles.srt');
} catch (e) {
alert("Error applying patches: " + e.message);
}
});
}
/**
* Replaces blocks in the original SRT with the corrected blocks.
*/
function patchSrtFile(originalText, corrections) {
// 1. Split original SRT into blocks (Double newline separator)
// Normalize line endings to \n first
const normalizedText = originalText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
let blocks = normalizedText.split(/\n\n+/);
// 2. Create a Map for faster updates
// We map "ID" -> Index in the blocks array
let blockMap = new Map();
blocks.forEach((block, index) => {
const lines = block.trim().split('\n');
if (lines.length > 0) {
const id = lines[0].trim();
// Store the index so we can update the array directly
blockMap.set(id, index);
}
});
// 3. Apply Corrections
let appliedCount = 0;
corrections.forEach(fix => {
// Extract ID from the CORRECTION block (it's usually the first line)
// Example fix.correctedSrt: "10\n00:00:10 --> ... \nHello"
if (!fix.correctedSrt) return;
const fixLines = fix.correctedSrt.trim().split('\n');
const fixId = fixLines[0].trim();
if (blockMap.has(fixId)) {
const originalIndex = blockMap.get(fixId);
// REPLACE the entire original block with the new corrected block
blocks[originalIndex] = fix.correctedSrt.trim();
appliedCount++;
}
});
console.log(`Applied ${appliedCount} corrections.`);
return blocks.join('\n\n');
}
function downloadFile(content, filename) {
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
});