BoxOfColors commited on
Commit
78d7cea
·
1 Parent(s): 42b7d7f
Files changed (1) hide show
  1. app.py +27 -8
app.py CHANGED
@@ -1290,6 +1290,15 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1290
  plugins = [regionsPlugin];
1291
  }}
1292
 
 
 
 
 
 
 
 
 
 
1293
  // Wait until the container has a non-zero width before creating WaveSurfer,
1294
  // otherwise it renders blank (container is 0px when Gradio first injects HTML).
1295
  const wfContainer = document.getElementById('wf_{slot_id}');
@@ -1302,7 +1311,7 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1302
  barWidth: 2,
1303
  barGap: 1,
1304
  barRadius: 2,
1305
- url: '{data_uri}',
1306
  plugins: plugins,
1307
  }});
1308
 
@@ -1310,7 +1319,6 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1310
  ws.setVolume(0);
1311
  ws.on('ready', function() {{
1312
  ws.setVolume(0);
1313
- // Prevent WaveSurfer from auto-playing (it shouldn't, but be safe)
1314
  ws.pause();
1315
  const segments = {segs_json};
1316
  const colors = {json.dumps(colors)};
@@ -1335,6 +1343,10 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1335
  attachVideoSync(ws);
1336
  }});
1337
 
 
 
 
 
1338
  // Also silence if WaveSurfer tries to play for any reason
1339
  ws.on('play', function() {{ ws.pause(); ws.setVolume(0); }});
1340
 
@@ -1355,10 +1367,10 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1355
  }}
1356
  }});
1357
  ro.observe(wfContainer);
1358
- // Fallback: also try after a short delay in case ResizeObserver fires late
1359
  setTimeout(function() {{
1360
  if (!window["_wf_ws_{slot_id}"]) {{ ro.disconnect(); createWS(); }}
1361
- }}, 800);
1362
  }} else {{
1363
  // Container not in DOM yet — wait for it
1364
  setTimeout(loadWS, 200);
@@ -1407,7 +1419,7 @@ def _make_output_slots(tab_prefix: str) -> tuple:
1407
  for i in range(MAX_SLOTS):
1408
  with gr.Group(visible=(i == 0)) as g:
1409
  slot_id = f"{tab_prefix}_{i}"
1410
- vids.append(gr.Video(label=f"Generation {i+1} — Video"))
1411
  waveforms.append(gr.HTML(
1412
  value="<p style='color:#888;font-size:12px'>Generate audio to see waveform.</p>",
1413
  label=f"Generation {i+1} — Waveform",
@@ -1475,9 +1487,16 @@ def _update_slot_visibility(n):
1475
  # ================================================================== #
1476
 
1477
  _SLOT_CSS = """
1478
- /* Cap generated videos so the waveform below is never pushed out of view */
1479
- .gradio-video video {
1480
- max-height: 340px;
 
 
 
 
 
 
 
1481
  object-fit: contain;
1482
  }
1483
  """
 
1290
  plugins = [regionsPlugin];
1291
  }}
1292
 
1293
+ // Convert base64 audio to a Blob URL — WaveSurfer v7 handles blob: URLs
1294
+ // much more reliably than data: URIs for waveform rendering.
1295
+ const b64 = '{b64}';
1296
+ const byteChars = atob(b64);
1297
+ const byteNums = new Uint8Array(byteChars.length);
1298
+ for (let i = 0; i < byteChars.length; i++) byteNums[i] = byteChars.charCodeAt(i);
1299
+ const blob = new Blob([byteNums], {{type: 'audio/wav'}});
1300
+ const blobUrl = URL.createObjectURL(blob);
1301
+
1302
  // Wait until the container has a non-zero width before creating WaveSurfer,
1303
  // otherwise it renders blank (container is 0px when Gradio first injects HTML).
1304
  const wfContainer = document.getElementById('wf_{slot_id}');
 
1311
  barWidth: 2,
1312
  barGap: 1,
1313
  barRadius: 2,
1314
+ url: blobUrl,
1315
  plugins: plugins,
1316
  }});
1317
 
 
1319
  ws.setVolume(0);
1320
  ws.on('ready', function() {{
1321
  ws.setVolume(0);
 
1322
  ws.pause();
1323
  const segments = {segs_json};
1324
  const colors = {json.dumps(colors)};
 
1343
  attachVideoSync(ws);
1344
  }});
1345
 
1346
+ ws.on('error', function(err) {{
1347
+ console.error('[WaveSurfer {slot_id}] error:', err);
1348
+ }});
1349
+
1350
  // Also silence if WaveSurfer tries to play for any reason
1351
  ws.on('play', function() {{ ws.pause(); ws.setVolume(0); }});
1352
 
 
1367
  }}
1368
  }});
1369
  ro.observe(wfContainer);
1370
+ // Fallback after 1s in case ResizeObserver fires late
1371
  setTimeout(function() {{
1372
  if (!window["_wf_ws_{slot_id}"]) {{ ro.disconnect(); createWS(); }}
1373
+ }}, 1000);
1374
  }} else {{
1375
  // Container not in DOM yet — wait for it
1376
  setTimeout(loadWS, 200);
 
1419
  for i in range(MAX_SLOTS):
1420
  with gr.Group(visible=(i == 0)) as g:
1421
  slot_id = f"{tab_prefix}_{i}"
1422
+ vids.append(gr.Video(label=f"Generation {i+1} — Video", height=340))
1423
  waveforms.append(gr.HTML(
1424
  value="<p style='color:#888;font-size:12px'>Generate audio to see waveform.</p>",
1425
  label=f"Generation {i+1} — Waveform",
 
1487
  # ================================================================== #
1488
 
1489
  _SLOT_CSS = """
1490
+ /* Cap the entire video component (including the loading/processing state)
1491
+ so the waveform below is never pushed out of view */
1492
+ .gradio-video {
1493
+ max-height: 380px !important;
1494
+ overflow: hidden;
1495
+ }
1496
+ .gradio-video video,
1497
+ .gradio-video .video-container,
1498
+ .gradio-video .wrap {
1499
+ max-height: 340px !important;
1500
  object-fit: contain;
1501
  }
1502
  """