Commit ·
34cf138
1
Parent(s): bb533eb
Fix regen: add _listenAndApply SSE handler + elem_id on output slots
Browse files
app.py
CHANGED
|
@@ -1416,10 +1416,13 @@ def _make_output_slots(tab_prefix: str) -> tuple:
|
|
| 1416 |
"""
|
| 1417 |
grps, vids, waveforms = [], [], []
|
| 1418 |
for i in range(MAX_SLOTS):
|
|
|
|
| 1419 |
with gr.Group(visible=(i == 0)) as g:
|
| 1420 |
-
vids.append(gr.Video(label=f"Generation {i+1} — Video"
|
|
|
|
| 1421 |
waveforms.append(gr.HTML(
|
| 1422 |
value="<p style='color:#888;font-size:12px'>Generate audio to see waveform.</p>",
|
|
|
|
| 1423 |
))
|
| 1424 |
grps.append(g)
|
| 1425 |
return grps, vids, waveforms
|
|
@@ -1597,6 +1600,10 @@ _GLOBAL_JS = """
|
|
| 1597 |
|
| 1598 |
console.log('[fireRegen] calling api', apiName, 'fn_index', fnIndex, 'seg', seg_idx);
|
| 1599 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1600 |
fetch('/gradio_api/queue/join', {
|
| 1601 |
method: 'POST',
|
| 1602 |
headers: {'Content-Type': 'application/json'},
|
|
@@ -1608,14 +1615,71 @@ _GLOBAL_JS = """
|
|
| 1608 |
trigger_id: null
|
| 1609 |
})
|
| 1610 |
}).then(function(r) { return r.json(); }).then(function(j) {
|
|
|
|
| 1611 |
console.log('[fireRegen] queued, event_id:', j.event_id);
|
| 1612 |
-
|
| 1613 |
-
|
| 1614 |
}).catch(function(e) {
|
| 1615 |
console.error('[fireRegen] fetch error:', e);
|
|
|
|
| 1616 |
});
|
| 1617 |
}
|
| 1618 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1619 |
// Shared popup element created once and reused across all slots
|
| 1620 |
let _popup = null;
|
| 1621 |
let _pendingSlot = null, _pendingIdx = null;
|
|
|
|
| 1416 |
"""
|
| 1417 |
grps, vids, waveforms = [], [], []
|
| 1418 |
for i in range(MAX_SLOTS):
|
| 1419 |
+
slot_id = f"{tab_prefix}_{i}"
|
| 1420 |
with gr.Group(visible=(i == 0)) as g:
|
| 1421 |
+
vids.append(gr.Video(label=f"Generation {i+1} — Video",
|
| 1422 |
+
elem_id=f"slot_vid_{slot_id}"))
|
| 1423 |
waveforms.append(gr.HTML(
|
| 1424 |
value="<p style='color:#888;font-size:12px'>Generate audio to see waveform.</p>",
|
| 1425 |
+
elem_id=f"slot_wave_{slot_id}",
|
| 1426 |
))
|
| 1427 |
grps.append(g)
|
| 1428 |
return grps, vids, waveforms
|
|
|
|
| 1600 |
|
| 1601 |
console.log('[fireRegen] calling api', apiName, 'fn_index', fnIndex, 'seg', seg_idx);
|
| 1602 |
|
| 1603 |
+
// Show spinner immediately
|
| 1604 |
+
const lbl = document.getElementById('wf_seglabel_' + slot_id);
|
| 1605 |
+
if (lbl) lbl.textContent = 'Regenerating Seg ' + (seg_idx + 1) + '...';
|
| 1606 |
+
|
| 1607 |
fetch('/gradio_api/queue/join', {
|
| 1608 |
method: 'POST',
|
| 1609 |
headers: {'Content-Type': 'application/json'},
|
|
|
|
| 1615 |
trigger_id: null
|
| 1616 |
})
|
| 1617 |
}).then(function(r) { return r.json(); }).then(function(j) {
|
| 1618 |
+
if (!j.event_id) { console.error('[fireRegen] no event_id:', j); return; }
|
| 1619 |
console.log('[fireRegen] queued, event_id:', j.event_id);
|
| 1620 |
+
// Subscribe to SSE stream and apply outputs when ready
|
| 1621 |
+
_listenAndApply(j.event_id, slot_id, seg_idx);
|
| 1622 |
}).catch(function(e) {
|
| 1623 |
console.error('[fireRegen] fetch error:', e);
|
| 1624 |
+
if (lbl) lbl.textContent = 'Error — see console';
|
| 1625 |
});
|
| 1626 |
}
|
| 1627 |
|
| 1628 |
+
// Subscribe to Gradio SSE stream for an event and apply outputs to DOM.
|
| 1629 |
+
// For regen handlers, output[0] = video update, output[1] = waveform HTML update.
|
| 1630 |
+
function _listenAndApply(eventId, slot_id, seg_idx) {
|
| 1631 |
+
const es = new EventSource('/gradio_api/queue/data?session_hash=' + window.__gradio_session_hash__);
|
| 1632 |
+
es.onmessage = function(e) {
|
| 1633 |
+
var msg;
|
| 1634 |
+
try { msg = JSON.parse(e.data); } catch(_) { return; }
|
| 1635 |
+
if (msg.event_id !== eventId) return;
|
| 1636 |
+
if (msg.msg === 'process_generating' || msg.msg === 'process_completed') {
|
| 1637 |
+
var out = msg.output;
|
| 1638 |
+
if (out && out.data) {
|
| 1639 |
+
// data[0] = video update, data[1] = waveform HTML update
|
| 1640 |
+
var vidUpdate = out.data[0];
|
| 1641 |
+
var waveUpdate = out.data[1];
|
| 1642 |
+
// Apply video: update the <video> src inside the slot_vid element
|
| 1643 |
+
if (vidUpdate && vidUpdate.value) {
|
| 1644 |
+
var vidEl = document.getElementById('slot_vid_' + slot_id);
|
| 1645 |
+
if (vidEl) {
|
| 1646 |
+
var video = vidEl.querySelector('video');
|
| 1647 |
+
if (video) {
|
| 1648 |
+
var newSrc = vidUpdate.value.url || vidUpdate.value;
|
| 1649 |
+
if (typeof newSrc === 'string') {
|
| 1650 |
+
video.src = newSrc;
|
| 1651 |
+
video.load();
|
| 1652 |
+
}
|
| 1653 |
+
}
|
| 1654 |
+
}
|
| 1655 |
+
}
|
| 1656 |
+
// Apply waveform HTML: update innerHTML of the slot_wave element
|
| 1657 |
+
if (waveUpdate && waveUpdate.value) {
|
| 1658 |
+
var waveEl = document.getElementById('slot_wave_' + slot_id);
|
| 1659 |
+
if (waveEl) {
|
| 1660 |
+
// Find the inner content div (Gradio wraps HTML component)
|
| 1661 |
+
var inner = waveEl.querySelector('.prose') || waveEl.querySelector('div');
|
| 1662 |
+
if (inner) inner.innerHTML = waveUpdate.value;
|
| 1663 |
+
else waveEl.innerHTML = waveUpdate.value;
|
| 1664 |
+
// Also update the data-state on the new wf_container
|
| 1665 |
+
var newContainer = waveEl.querySelector('#wf_container_' + slot_id);
|
| 1666 |
+
// data-state is already embedded in the returned HTML
|
| 1667 |
+
}
|
| 1668 |
+
}
|
| 1669 |
+
}
|
| 1670 |
+
if (msg.msg === 'process_completed') {
|
| 1671 |
+
es.close();
|
| 1672 |
+
var lbl = document.getElementById('wf_seglabel_' + slot_id);
|
| 1673 |
+
if (lbl) lbl.textContent = msg.output && msg.output.error ?
|
| 1674 |
+
'Error regenerating' : 'Done';
|
| 1675 |
+
console.log('[fireRegen] completed for', slot_id, 'success:', msg.success);
|
| 1676 |
+
}
|
| 1677 |
+
}
|
| 1678 |
+
if (msg.msg === 'close_stream') { es.close(); }
|
| 1679 |
+
};
|
| 1680 |
+
es.onerror = function() { es.close(); };
|
| 1681 |
+
}
|
| 1682 |
+
|
| 1683 |
// Shared popup element created once and reused across all slots
|
| 1684 |
let _popup = null;
|
| 1685 |
let _pendingSlot = null, _pendingIdx = null;
|