Spaces:
Running on Zero
Running on Zero
Commit ·
0219f72
1
Parent(s): 1ccc3d0
Fix video update after regen: delay+MutationObserver to survive Svelte re-render
Browse files
app.py
CHANGED
|
@@ -1636,7 +1636,21 @@ _GLOBAL_JS = """
|
|
| 1636 |
|
| 1637 |
// Subscribe to Gradio SSE stream for an event and apply outputs to DOM.
|
| 1638 |
// For regen handlers, output[0] = video update, output[1] = waveform HTML update.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1639 |
function _listenAndApply(eventId, slot_id, seg_idx) {
|
|
|
|
| 1640 |
const es = new EventSource('/gradio_api/queue/data?session_hash=' + window.__gradio_session_hash__);
|
| 1641 |
es.onmessage = function(e) {
|
| 1642 |
var msg;
|
|
@@ -1648,48 +1662,26 @@ _GLOBAL_JS = """
|
|
| 1648 |
// data[0] = video update, data[1] = waveform HTML update
|
| 1649 |
var vidUpdate = out.data[0];
|
| 1650 |
var waveUpdate = out.data[1];
|
| 1651 |
-
console.log('[_listenAndApply] vidUpdate raw:', JSON.stringify(vidUpdate));
|
| 1652 |
-
console.log('[_listenAndApply] waveUpdate type:', typeof waveUpdate,
|
| 1653 |
-
waveUpdate && typeof waveUpdate === 'object' ? Object.keys(waveUpdate) : waveUpdate && String(waveUpdate).slice(0,80));
|
| 1654 |
|
| 1655 |
-
// Extract video URL — Gradio 5
|
| 1656 |
-
//
|
| 1657 |
var newSrc = null;
|
| 1658 |
if (vidUpdate) {
|
| 1659 |
-
if (vidUpdate.video && vidUpdate.video.url) {
|
| 1660 |
-
newSrc = vidUpdate.video.url;
|
| 1661 |
-
} else if (vidUpdate.
|
| 1662 |
-
newSrc = vidUpdate.
|
| 1663 |
} else if (vidUpdate.value && vidUpdate.value.url) {
|
| 1664 |
newSrc = vidUpdate.value.url; // older style
|
| 1665 |
} else if (typeof vidUpdate.value === 'string') {
|
| 1666 |
-
newSrc = vidUpdate.value;
|
| 1667 |
} else if (vidUpdate.url) {
|
| 1668 |
-
newSrc = vidUpdate.url;
|
| 1669 |
-
}
|
| 1670 |
-
}
|
| 1671 |
-
console.log('[_listenAndApply] resolved video src:', newSrc);
|
| 1672 |
-
|
| 1673 |
-
// Apply video: update the <video> src inside the slot_vid element
|
| 1674 |
-
if (newSrc) {
|
| 1675 |
-
var vidEl = document.getElementById('slot_vid_' + slot_id);
|
| 1676 |
-
if (vidEl) {
|
| 1677 |
-
var video = vidEl.querySelector('video');
|
| 1678 |
-
if (video) {
|
| 1679 |
-
// Gradio 5 uses Svelte — set src attribute AND property to force reload
|
| 1680 |
-
video.setAttribute('src', newSrc);
|
| 1681 |
-
video.src = newSrc;
|
| 1682 |
-
video.load();
|
| 1683 |
-
console.log('[_listenAndApply] set video src on', 'slot_vid_' + slot_id);
|
| 1684 |
-
} else {
|
| 1685 |
-
console.warn('[_listenAndApply] no <video> element found inside', 'slot_vid_' + slot_id);
|
| 1686 |
-
}
|
| 1687 |
-
} else {
|
| 1688 |
-
console.warn('[_listenAndApply] no element with id slot_vid_' + slot_id);
|
| 1689 |
}
|
| 1690 |
}
|
|
|
|
| 1691 |
|
| 1692 |
-
// Apply waveform HTML
|
| 1693 |
var waveHtml = null;
|
| 1694 |
if (waveUpdate) {
|
| 1695 |
if (typeof waveUpdate === 'string') {
|
|
@@ -1701,19 +1693,38 @@ _GLOBAL_JS = """
|
|
| 1701 |
if (waveHtml) {
|
| 1702 |
var waveEl = document.getElementById('slot_wave_' + slot_id);
|
| 1703 |
if (waveEl) {
|
| 1704 |
-
// Find the inner content div (Gradio wraps HTML component)
|
| 1705 |
var inner = waveEl.querySelector('.prose') || waveEl.querySelector('div');
|
| 1706 |
if (inner) inner.innerHTML = waveHtml;
|
| 1707 |
else waveEl.innerHTML = waveHtml;
|
| 1708 |
}
|
| 1709 |
}
|
| 1710 |
}
|
|
|
|
| 1711 |
if (msg.msg === 'process_completed') {
|
| 1712 |
es.close();
|
| 1713 |
var lbl = document.getElementById('wf_seglabel_' + slot_id);
|
| 1714 |
if (lbl) lbl.textContent = msg.output && msg.output.error ?
|
| 1715 |
'Error regenerating' : 'Done';
|
| 1716 |
console.log('[fireRegen] completed for', slot_id, 'success:', msg.success);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1717 |
}
|
| 1718 |
}
|
| 1719 |
if (msg.msg === 'close_stream') { es.close(); }
|
|
|
|
| 1636 |
|
| 1637 |
// Subscribe to Gradio SSE stream for an event and apply outputs to DOM.
|
| 1638 |
// For regen handlers, output[0] = video update, output[1] = waveform HTML update.
|
| 1639 |
+
function _applyVideoSrc(slot_id, newSrc) {
|
| 1640 |
+
var vidEl = document.getElementById('slot_vid_' + slot_id);
|
| 1641 |
+
if (!vidEl) return false;
|
| 1642 |
+
var video = vidEl.querySelector('video');
|
| 1643 |
+
if (!video) return false;
|
| 1644 |
+
if (video.getAttribute('src') === newSrc) return true; // already correct
|
| 1645 |
+
video.setAttribute('src', newSrc);
|
| 1646 |
+
video.src = newSrc;
|
| 1647 |
+
video.load();
|
| 1648 |
+
console.log('[_applyVideoSrc] applied src to', 'slot_vid_' + slot_id, 'src:', newSrc.slice(-40));
|
| 1649 |
+
return true;
|
| 1650 |
+
}
|
| 1651 |
+
|
| 1652 |
function _listenAndApply(eventId, slot_id, seg_idx) {
|
| 1653 |
+
var _pendingVideoSrc = null; // track the latest resolved video URL
|
| 1654 |
const es = new EventSource('/gradio_api/queue/data?session_hash=' + window.__gradio_session_hash__);
|
| 1655 |
es.onmessage = function(e) {
|
| 1656 |
var msg;
|
|
|
|
| 1662 |
// data[0] = video update, data[1] = waveform HTML update
|
| 1663 |
var vidUpdate = out.data[0];
|
| 1664 |
var waveUpdate = out.data[1];
|
|
|
|
|
|
|
|
|
|
| 1665 |
|
| 1666 |
+
// Extract video URL — Gradio 5 wraps final output as
|
| 1667 |
+
// {value:{video:{url:"..."},subtitles:null},__type__:"update"}
|
| 1668 |
var newSrc = null;
|
| 1669 |
if (vidUpdate) {
|
| 1670 |
+
if (vidUpdate.value && vidUpdate.value.video && vidUpdate.value.video.url) {
|
| 1671 |
+
newSrc = vidUpdate.value.video.url; // final update shape
|
| 1672 |
+
} else if (vidUpdate.video && vidUpdate.video.url) {
|
| 1673 |
+
newSrc = vidUpdate.video.url; // direct shape
|
| 1674 |
} else if (vidUpdate.value && vidUpdate.value.url) {
|
| 1675 |
newSrc = vidUpdate.value.url; // older style
|
| 1676 |
} else if (typeof vidUpdate.value === 'string') {
|
| 1677 |
+
newSrc = vidUpdate.value;
|
| 1678 |
} else if (vidUpdate.url) {
|
| 1679 |
+
newSrc = vidUpdate.url;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1680 |
}
|
| 1681 |
}
|
| 1682 |
+
if (newSrc) _pendingVideoSrc = newSrc;
|
| 1683 |
|
| 1684 |
+
// Apply waveform HTML immediately (waveform is plain HTML, no Svelte reactivity)
|
| 1685 |
var waveHtml = null;
|
| 1686 |
if (waveUpdate) {
|
| 1687 |
if (typeof waveUpdate === 'string') {
|
|
|
|
| 1693 |
if (waveHtml) {
|
| 1694 |
var waveEl = document.getElementById('slot_wave_' + slot_id);
|
| 1695 |
if (waveEl) {
|
|
|
|
| 1696 |
var inner = waveEl.querySelector('.prose') || waveEl.querySelector('div');
|
| 1697 |
if (inner) inner.innerHTML = waveHtml;
|
| 1698 |
else waveEl.innerHTML = waveHtml;
|
| 1699 |
}
|
| 1700 |
}
|
| 1701 |
}
|
| 1702 |
+
|
| 1703 |
if (msg.msg === 'process_completed') {
|
| 1704 |
es.close();
|
| 1705 |
var lbl = document.getElementById('wf_seglabel_' + slot_id);
|
| 1706 |
if (lbl) lbl.textContent = msg.output && msg.output.error ?
|
| 1707 |
'Error regenerating' : 'Done';
|
| 1708 |
console.log('[fireRegen] completed for', slot_id, 'success:', msg.success);
|
| 1709 |
+
|
| 1710 |
+
// Apply video src AFTER Gradio/Svelte finishes its own re-render cycle.
|
| 1711 |
+
// We try at 50ms, 300ms, and 800ms to catch whenever Svelte settles.
|
| 1712 |
+
var src = _pendingVideoSrc;
|
| 1713 |
+
if (src) {
|
| 1714 |
+
_applyVideoSrc(slot_id, src);
|
| 1715 |
+
setTimeout(function() { _applyVideoSrc(slot_id, src); }, 50);
|
| 1716 |
+
setTimeout(function() { _applyVideoSrc(slot_id, src); }, 300);
|
| 1717 |
+
setTimeout(function() { _applyVideoSrc(slot_id, src); }, 800);
|
| 1718 |
+
// Also install a MutationObserver for 2s to re-apply if Svelte resets src
|
| 1719 |
+
var vidEl = document.getElementById('slot_vid_' + slot_id);
|
| 1720 |
+
if (vidEl) {
|
| 1721 |
+
var obs = new MutationObserver(function() {
|
| 1722 |
+
_applyVideoSrc(slot_id, src);
|
| 1723 |
+
});
|
| 1724 |
+
obs.observe(vidEl, {subtree: true, attributes: true, attributeFilter: ['src'], childList: true});
|
| 1725 |
+
setTimeout(function() { obs.disconnect(); }, 2000);
|
| 1726 |
+
}
|
| 1727 |
+
}
|
| 1728 |
}
|
| 1729 |
}
|
| 1730 |
if (msg.msg === 'close_stream') { es.close(); }
|