duongthienz commited on
Commit
5b6cb3e
·
verified ·
1 Parent(s): 835eb03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -27
app.py CHANGED
@@ -53,7 +53,51 @@ def apply_speaker_renames_to_df(df, fileIndex, column="task"):
53
  df = df.copy()
54
  df[column] = df[column].apply(lambda s: get_display_name(s, fileIndex))
55
  return df
56
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  @st.cache_data
58
  def convert_df(df):
59
  return df.to_csv(index=False).encode('utf-8')
@@ -115,23 +159,7 @@ def processFile(filePath):
115
  totalTimeInSeconds = int(waveform_gain_adjusted.shape[-1]/sampleRate)
116
  print("Time in seconds calculated")
117
  return annotations, totalTimeInSeconds
118
-
119
- @st.cache_data
120
- def extract_speaker_clip(file_path, speaker, _annotation, clip_duration=5.0):
121
- waveform, sample_rate = torchaudio.load(file_path)
122
- for segment, _, label in _annotation.itertracks(yield_label=True):
123
- if label == speaker and segment.duration >= 1.0:
124
- start_sample = int(segment.start * sample_rate)
125
- end_sample = int(min(segment.start + clip_duration, segment.end) * sample_rate)
126
- clip = waveform[:, start_sample:end_sample]
127
- # Convert to wav bytes in memory
128
- import io
129
- buf = io.BytesIO()
130
- torchaudio.save(buf, clip, sample_rate, format="wav")
131
- buf.seek(0)
132
- return buf.read()
133
- return None
134
-
135
  def addCategory():
136
  newCategory = st.session_state.categoryInput
137
  st.toast(f"Adding {newCategory}")
@@ -622,21 +650,39 @@ try:
622
 
623
  newCategory = st.sidebar.text_input('Add category', key='categoryInput',on_change=addCategory)
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  st.sidebar.divider()
626
  st.sidebar.subheader("Rename Speakers")
627
- st.sidebar.caption("Replace SPEAKER_## labels with real names. Listen to a sample clip to help identify each speaker.")
628
  current_renames = st.session_state.speakerRenames[currFileIndex]
629
- currFilePath = st.session_state.file_paths[currFileIndex]
630
  for sp in speakerNames:
631
  current_label = current_renames.get(sp, "")
632
- st.sidebar.markdown(f"**{sp}**")
633
- # Only show audio player for real audio files (not rttm/csv/txt)
634
- if currFilePath.lower().endswith(('.wav', '.mp3', '.mp4')):
635
- clip_bytes = extract_speaker_clip(currFilePath, sp, currAnnotation)
636
- if clip_bytes:
637
- st.sidebar.audio(clip_bytes, format="audio/wav")
638
  new_name = st.sidebar.text_input(
639
- f"Rename {sp}",
640
  value=current_label,
641
  placeholder=f"e.g. John",
642
  key=f"rename_{currFileIndex}_{sp}"
 
53
  df = df.copy()
54
  df[column] = df[column].apply(lambda s: get_display_name(s, fileIndex))
55
  return df
56
+
57
+ def extract_speaker_clip(audio_path, annotation, speaker, clip_duration=5):
58
+ """
59
+ Extract a clip of up to clip_duration seconds for the given speaker.
60
+ Prefers the first segment >= clip_duration seconds; falls back to the longest segment.
61
+ Returns bytes (WAV) or None on failure.
62
+ """
63
+ try:
64
+ import io
65
+ # Collect all segments for this speaker
66
+ speaker_segments = [
67
+ (seg.start, seg.end)
68
+ for seg, _, label in annotation.itertracks(yield_label=True)
69
+ if label == speaker
70
+ ]
71
+ if not speaker_segments:
72
+ return None
73
+
74
+ # Prefer first segment long enough for a full clip
75
+ chosen_start, chosen_end = None, None
76
+ for start, end in speaker_segments:
77
+ if (end - start) >= clip_duration:
78
+ chosen_start, chosen_end = start, start + clip_duration
79
+ break
80
+
81
+ # Fall back: use the longest segment available
82
+ if chosen_start is None:
83
+ longest = max(speaker_segments, key=lambda s: s[1] - s[0])
84
+ chosen_start, chosen_end = longest
85
+
86
+ # Load audio and slice the clip
87
+ waveform, sample_rate = torchaudio.load(audio_path)
88
+ start_frame = int(chosen_start * sample_rate)
89
+ end_frame = min(int(chosen_end * sample_rate), waveform.shape[-1])
90
+ clip = waveform[:, start_frame:end_frame]
91
+
92
+ # Encode as WAV in memory
93
+ buffer = io.BytesIO()
94
+ torchaudio.save(buffer, clip, sample_rate, format="wav")
95
+ buffer.seek(0)
96
+ return buffer.read()
97
+ except Exception as e:
98
+ print(f"extract_speaker_clip error for {speaker}: {e}")
99
+ return None
100
+
101
  @st.cache_data
102
  def convert_df(df):
103
  return df.to_csv(index=False).encode('utf-8')
 
159
  totalTimeInSeconds = int(waveform_gain_adjusted.shape[-1]/sampleRate)
160
  print("Time in seconds calculated")
161
  return annotations, totalTimeInSeconds
162
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  def addCategory():
164
  newCategory = st.session_state.categoryInput
165
  st.toast(f"Adding {newCategory}")
 
650
 
651
  newCategory = st.sidebar.text_input('Add category', key='categoryInput',on_change=addCategory)
652
 
653
+ # --- Speaker Sample Clips (audio files only) ---
654
+ _is_audio_file = currFile is not None and not any(
655
+ currFile.lower().endswith(ext) for ext in ('.rttm', '.txt', '.csv')
656
+ )
657
+ if _is_audio_file:
658
+ st.sidebar.divider()
659
+ st.sidebar.subheader("\U0001f3a7 Speaker Samples")
660
+ st.sidebar.caption(
661
+ "Listen to a 5-second clip for each speaker to help identify them."
662
+ )
663
+ _curr_audio_path = file_paths[currFileIndex] if currFileIndex < len(file_paths) else None
664
+ if _curr_audio_path and os.path.exists(_curr_audio_path):
665
+ for sp in speakerNames:
666
+ _display = get_display_name(sp, currFileIndex)
667
+ st.sidebar.markdown(f"**{_display}**")
668
+ _clip_bytes = extract_speaker_clip(
669
+ _curr_audio_path, currAnnotation, sp, clip_duration=5
670
+ )
671
+ if _clip_bytes:
672
+ st.sidebar.audio(_clip_bytes, format="audio/wav")
673
+ else:
674
+ st.sidebar.caption("_(No audio segment found)_")
675
+ else:
676
+ st.sidebar.caption("_(Audio file not available for preview)_")
677
+
678
  st.sidebar.divider()
679
  st.sidebar.subheader("Rename Speakers")
680
+ st.sidebar.caption("Replace SPEAKER_## labels with real names.")
681
  current_renames = st.session_state.speakerRenames[currFileIndex]
 
682
  for sp in speakerNames:
683
  current_label = current_renames.get(sp, "")
 
 
 
 
 
 
684
  new_name = st.sidebar.text_input(
685
+ f"{sp}",
686
  value=current_label,
687
  placeholder=f"e.g. John",
688
  key=f"rename_{currFileIndex}_{sp}"