BoxOfColors commited on
Commit
34cf138
·
1 Parent(s): bb533eb

Fix regen: add _listenAndApply SSE handler + elem_id on output slots

Browse files
Files changed (1) hide show
  1. app.py +67 -3
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
- const lbl = document.getElementById('wf_seglabel_' + slot_id);
1613
- if (lbl) lbl.textContent = 'Regenerating Seg ' + (seg_idx + 1) + '...';
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;