Enable tiled_vae to prevent OOM on portrait images
Some checks failed
Build and Push Docker Image / build (push) Failing after 29m0s

Also add async polling to HTML test page for long-running jobs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-01-04 02:23:46 +00:00
parent c04e4b6250
commit bcb39c615d
2 changed files with 103 additions and 37 deletions

View File

@@ -456,6 +456,107 @@
document.getElementById('status').classList.remove('show');
}
async function pollForCompletion(endpointId, jobId, apiKey, startTime) {
const statusUrl = `https://api.runpod.ai/v2/${endpointId}/status/${jobId}`;
const maxPolls = 120; // 10 minutes with 5s intervals
let pollCount = 0;
while (pollCount < maxPolls) {
pollCount++;
const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);
showStatus(`⏳ Generating video... (${elapsed}s elapsed, poll #${pollCount})`, 'info');
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
try {
const response = await fetch(statusUrl, {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const result = await response.json();
// Update JSON output
document.getElementById('jsonOutput').innerHTML =
'<strong>Raw Response:</strong><pre>' +
JSON.stringify(result, null, 2) +
'</pre>';
if (result.status === 'COMPLETED' || result.status === 'FAILED') {
return result;
}
// Still in progress, continue polling
} catch (error) {
console.error('Poll error:', error);
// Continue polling despite errors
}
}
throw new Error('Timeout: Job did not complete within 10 minutes');
}
async function handleResult(result, startTime, endpointId, apiKey) {
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
// If still in progress, poll for completion
if (result.status === 'IN_PROGRESS' || result.status === 'IN_QUEUE') {
showStatus(`⏳ Job ${result.id} is ${result.status}. Polling for completion...`, 'info');
result = await pollForCompletion(endpointId, result.id, apiKey, startTime);
// Update JSON output with final result
document.getElementById('jsonOutput').innerHTML =
'<strong>Raw Response:</strong><pre>' +
JSON.stringify(result, null, 2) +
'</pre>';
}
const finalElapsed = ((Date.now() - startTime) / 1000).toFixed(2);
if (result.status === 'COMPLETED' && result.output) {
showStatus(`✅ Video generated successfully in ${finalElapsed}s`, 'success');
const outputContainer = document.getElementById('outputContainer');
if (result.output.video) {
// Base64 video
const videoElem = document.createElement('video');
videoElem.className = 'output-video';
videoElem.controls = true;
videoElem.autoplay = true;
videoElem.loop = true;
videoElem.src = 'data:video/mp4;base64,' + result.output.video;
outputContainer.appendChild(videoElem);
} else if (result.output.image) {
// Base64 image
const imgElem = document.createElement('img');
imgElem.className = 'output-video';
imgElem.src = 'data:image/png;base64,' + result.output.image;
outputContainer.appendChild(imgElem);
} else if (result.output.file_path) {
// File path (large output)
const fileInfo = document.createElement('div');
fileInfo.className = 'status info show';
fileInfo.innerHTML = `
<strong>Large output saved to:</strong><br>
<code>${result.output.file_path}</code><br><br>
<em>File is too large to display (>10MB). Access it on your RunPod volume.</em>
`;
outputContainer.appendChild(fileInfo);
}
} else if (result.status === 'FAILED') {
showStatus('❌ Generation failed: ' + (result.error || 'Unknown error'), 'error');
} else {
showStatus('⚠️ Unexpected response status: ' + result.status, 'error');
}
}
async function submitRequest() {
// Validation
const endpointId = document.getElementById('endpointId').value.trim();
@@ -531,42 +632,7 @@
'</pre>';
// Handle response
if (result.status === 'COMPLETED' && result.output) {
showStatus(`✅ Video generated successfully in ${elapsed}s`, 'success');
const outputContainer = document.getElementById('outputContainer');
if (result.output.video) {
// Base64 video
const videoElem = document.createElement('video');
videoElem.className = 'output-video';
videoElem.controls = true;
videoElem.autoplay = true;
videoElem.loop = true;
videoElem.src = 'data:video/mp4;base64,' + result.output.video;
outputContainer.appendChild(videoElem);
} else if (result.output.image) {
// Base64 image
const imgElem = document.createElement('img');
imgElem.className = 'output-video';
imgElem.src = 'data:image/png;base64,' + result.output.image;
outputContainer.appendChild(imgElem);
} else if (result.output.file_path) {
// File path (large output)
const fileInfo = document.createElement('div');
fileInfo.className = 'status info show';
fileInfo.innerHTML = `
<strong>Large output saved to:</strong><br>
<code>${result.output.file_path}</code><br><br>
<em>File is too large to display (>10MB). Access it on your RunPod volume.</em>
`;
outputContainer.appendChild(fileInfo);
}
} else if (result.status === 'FAILED') {
showStatus('❌ Generation failed: ' + (result.error || 'Unknown error'), 'error');
} else {
showStatus('⚠️ Unexpected response status: ' + result.status, 'error');
}
await handleResult(result, startTime, endpointId, apiKey);
} catch (error) {
showStatus('❌ Error: ' + error.message, 'error');