Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Replace st.dataframe(displayDF) with a custom table
Browse filesStreamlit's dataframe widget is read-only and renders only scalar values β it cannot embed audio players or buttons. We have to hand-render the table using st.columns
app.py
CHANGED
|
@@ -362,28 +362,7 @@ try:
|
|
| 362 |
"Changes apply to all matched speakers instantly."
|
| 363 |
)
|
| 364 |
|
| 365 |
-
|
| 366 |
-
if file_clips:
|
| 367 |
-
st.sidebar.caption("π§ Listen to clips to help identify speakers:")
|
| 368 |
-
current_renames = st.session_state.speakerRenames[currFile]
|
| 369 |
-
for sp in speakerNames:
|
| 370 |
-
wk = f"rename_{currFile}_{sp}"
|
| 371 |
-
if wk not in st.session_state:
|
| 372 |
-
st.session_state[wk] = current_renames.get(sp, "")
|
| 373 |
-
display_label = st.session_state[wk].strip() or sp
|
| 374 |
-
st.sidebar.markdown(f"**{display_label}**")
|
| 375 |
-
if sp in file_clips:
|
| 376 |
-
st.sidebar.audio(file_clips[sp], format="audio/wav")
|
| 377 |
-
sp_segs = st.session_state.speakerSegments.get(currFile, {}).get(sp, [])
|
| 378 |
-
has_waveform = currFile in st.session_state.speakerWaveforms
|
| 379 |
-
if has_waveform and sp_segs:
|
| 380 |
-
if st.sidebar.button(
|
| 381 |
-
"π Try Another Clip",
|
| 382 |
-
key=f"randomize_{currFile}_{sp}",
|
| 383 |
-
help="Pick a random clip from a different part of this speaker's audio",
|
| 384 |
-
):
|
| 385 |
-
randomize_speaker_clip(currFile, sp)
|
| 386 |
-
st.rerun()
|
| 387 |
|
| 388 |
all_speaker_tokens = [
|
| 389 |
f"{fn}: {sp}"
|
|
@@ -456,7 +435,65 @@ try:
|
|
| 456 |
f"sonogram-analysis-{currPlainName}.csv", "text/csv",
|
| 457 |
key="download-csv", on_click="ignore",
|
| 458 |
)
|
| 459 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 460 |
|
| 461 |
# -----------------------------------------------------------------------
|
| 462 |
# Charts (pie1, pie2, sunburst, treemap, timeline, bar)
|
|
|
|
| 362 |
"Changes apply to all matched speakers instantly."
|
| 363 |
)
|
| 364 |
|
| 365 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
|
| 367 |
all_speaker_tokens = [
|
| 368 |
f"{fn}: {sp}"
|
|
|
|
| 435 |
f"sonogram-analysis-{currPlainName}.csv", "text/csv",
|
| 436 |
key="download-csv", on_click="ignore",
|
| 437 |
)
|
| 438 |
+
|
| 439 |
+
file_clips = st.session_state.speakerClips.get(currFile, {})
|
| 440 |
+
has_clips = bool(file_clips)
|
| 441 |
+
has_waveform = currFile in st.session_state.speakerWaveforms
|
| 442 |
+
|
| 443 |
+
# Determine column layout.
|
| 444 |
+
# Extra columns only appear when audio clips are available.
|
| 445 |
+
# Widths: Resource | Start | Finish | [Clip | Randomize]
|
| 446 |
+
other_cols = [c for c in displayDF.columns if c != "Resource"]
|
| 447 |
+
has_extras = has_clips
|
| 448 |
+
|
| 449 |
+
if has_extras:
|
| 450 |
+
col_widths = [2] + [1] * len(other_cols) + [2, 1]
|
| 451 |
+
else:
|
| 452 |
+
col_widths = [2] + [1] * len(other_cols)
|
| 453 |
+
|
| 454 |
+
# Header row
|
| 455 |
+
header_cols = st.columns(col_widths)
|
| 456 |
+
header_cols[0].markdown("**Resource**")
|
| 457 |
+
for i, col_name in enumerate(other_cols):
|
| 458 |
+
header_cols[i + 1].markdown(f"**{col_name}**")
|
| 459 |
+
if has_extras:
|
| 460 |
+
header_cols[-2].markdown("**Clip**")
|
| 461 |
+
header_cols[-1].markdown("** **", unsafe_allow_html=True)
|
| 462 |
+
|
| 463 |
+
st.divider()
|
| 464 |
+
|
| 465 |
+
# Track which speakers have already had their clip rendered
|
| 466 |
+
# so we only show it once (on the first row for that speaker).
|
| 467 |
+
rendered_clip_for: set = set()
|
| 468 |
+
|
| 469 |
+
for _, row in displayDF.iterrows():
|
| 470 |
+
row_cols = st.columns(col_widths)
|
| 471 |
+
raw_sp = row["Resource"] # already display-name mapped
|
| 472 |
+
|
| 473 |
+
# Find the original raw speaker key for clip lookup
|
| 474 |
+
# (speakerClips is keyed by original SPEAKER_## labels)
|
| 475 |
+
raw_key = next(
|
| 476 |
+
(sp for sp in speakerNames if raw_to_display.get(sp, sp) == raw_sp),
|
| 477 |
+
raw_sp,
|
| 478 |
+
)
|
| 479 |
+
|
| 480 |
+
row_cols[0].write(raw_sp)
|
| 481 |
+
for i, col_name in enumerate(other_cols):
|
| 482 |
+
row_cols[i + 1].write(row[col_name])
|
| 483 |
+
|
| 484 |
+
if has_extras:
|
| 485 |
+
if raw_key in file_clips and raw_key not in rendered_clip_for:
|
| 486 |
+
rendered_clip_for.add(raw_key)
|
| 487 |
+
row_cols[-2].audio(file_clips[raw_key], format="audio/wav")
|
| 488 |
+
sp_segs = st.session_state.speakerSegments.get(currFile, {}).get(raw_key, [])
|
| 489 |
+
if has_waveform and sp_segs:
|
| 490 |
+
if row_cols[-1].button(
|
| 491 |
+
"π",
|
| 492 |
+
key=f"randomize_{currFile}_{raw_key}",
|
| 493 |
+
help="Try a different clip for this speaker",
|
| 494 |
+
):
|
| 495 |
+
randomize_speaker_clip(currFile, raw_key)
|
| 496 |
+
st.rerun()
|
| 497 |
|
| 498 |
# -----------------------------------------------------------------------
|
| 499 |
# Charts (pie1, pie2, sunburst, treemap, timeline, bar)
|