BoxOfColors commited on
Commit
42b7d7f
·
1 Parent(s): 4aa0f7d
Files changed (1) hide show
  1. app.py +79 -39
app.py CHANGED
@@ -1290,47 +1290,79 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
1290
  plugins = [regionsPlugin];
1291
  }}
1292
 
1293
- const ws = WaveSurfer.create({{
1294
- container: '#wf_{slot_id}',
1295
- waveColor: '#4a9eff',
1296
- progressColor: '#1a5fa8',
1297
- height: 80,
1298
- barWidth: 2,
1299
- barGap: 1,
1300
- barRadius: 2,
1301
- interact: false,
1302
- url: '{data_uri}',
1303
- plugins: plugins,
1304
- }});
1305
-
1306
- // Silence the WaveSurfer audio immediately and on ready
1307
- ws.setVolume(0);
1308
- ws.on('ready', function() {{
 
1309
  ws.setVolume(0);
1310
- const segments = {segs_json};
1311
- const colors = {json.dumps(colors)};
1312
- if (regionsPlugin) {{
1313
- segments.forEach(function(seg, idx) {{
1314
- regionsPlugin.addRegion({{
1315
- id: 'seg_' + idx,
1316
- start: seg[0],
1317
- end: seg[1],
1318
- color: colors[idx % colors.length],
1319
- drag: false,
1320
- resize: false,
1321
- content: 'Seg ' + (idx + 1),
 
 
 
 
 
1322
  }});
1323
- }});
1324
- regionsPlugin.on('region-clicked', function(region, e) {{
1325
- e.stopPropagation();
1326
- const idx = parseInt(region.id.replace('seg_', ''));
1327
- showPopup(idx, e.clientX, e.clientY);
1328
- }});
1329
- }}
1330
- attachVideoSync(ws);
1331
- }});
 
 
 
 
 
1332
 
1333
- window["_wf_ws_{slot_id}"] = ws;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1334
  }}
1335
 
1336
  // Load WaveSurfer + Regions scripts once (idempotent)
@@ -1442,7 +1474,15 @@ def _update_slot_visibility(n):
1442
  # GRADIO UI #
1443
  # ================================================================== #
1444
 
1445
- with gr.Blocks(title="Generate Audio for Video") as demo:
 
 
 
 
 
 
 
 
1446
  gr.Markdown(
1447
  "# Generate Audio for Video\n"
1448
  "Choose a model and upload a video to generate synchronized audio.\n\n"
 
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}');
1296
+ function createWS() {{
1297
+ const ws = WaveSurfer.create({{
1298
+ container: '#wf_{slot_id}',
1299
+ waveColor: '#4a9eff',
1300
+ progressColor: '#1a5fa8',
1301
+ height: 80,
1302
+ barWidth: 2,
1303
+ barGap: 1,
1304
+ barRadius: 2,
1305
+ url: '{data_uri}',
1306
+ plugins: plugins,
1307
+ }});
1308
+
1309
+ // Silence immediately — waveform is display-only, video plays the audio
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)};
1317
+ if (regionsPlugin) {{
1318
+ segments.forEach(function(seg, idx) {{
1319
+ regionsPlugin.addRegion({{
1320
+ id: 'seg_' + idx,
1321
+ start: seg[0],
1322
+ end: seg[1],
1323
+ color: colors[idx % colors.length],
1324
+ drag: false,
1325
+ resize: false,
1326
+ content: 'Seg ' + (idx + 1),
1327
+ }});
1328
  }});
1329
+ regionsPlugin.on('region-clicked', function(region, e) {{
1330
+ e.stopPropagation();
1331
+ const idx = parseInt(region.id.replace('seg_', ''));
1332
+ showPopup(idx, e.clientX, e.clientY);
1333
+ }});
1334
+ }}
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
+
1341
+ window["_wf_ws_{slot_id}"] = ws;
1342
+ }}
1343
 
1344
+ // Use ResizeObserver: fire createWS as soon as the container has width
1345
+ if (wfContainer && wfContainer.offsetWidth > 0) {{
1346
+ createWS();
1347
+ }} else if (wfContainer) {{
1348
+ const ro = new ResizeObserver(function(entries) {{
1349
+ for (const entry of entries) {{
1350
+ if (entry.contentRect.width > 0) {{
1351
+ ro.disconnect();
1352
+ createWS();
1353
+ break;
1354
+ }}
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);
1365
+ }}
1366
  }}
1367
 
1368
  // Load WaveSurfer + Regions scripts once (idempotent)
 
1474
  # GRADIO UI #
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
+ """
1484
+
1485
+ with gr.Blocks(title="Generate Audio for Video", css=_SLOT_CSS) as demo:
1486
  gr.Markdown(
1487
  "# Generate Audio for Video\n"
1488
  "Choose a model and upload a video to generate synchronized audio.\n\n"