duongthienz commited on
Commit
fbc8ee4
·
verified ·
1 Parent(s): 510fb60

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +320 -203
app.py CHANGED
@@ -22,6 +22,7 @@ from pyannote.audio import Pipeline
22
  from pyannote.core import Annotation, Segment, Timeline
23
  import datetime as dt
24
 
 
25
  earlyCleanup = True
26
 
27
  # [None,Low,Medium,High,Debug]
@@ -37,7 +38,22 @@ def printV(message,verbosityLevel):
37
  global verbosity
38
  if verbosity>=verbosityLevel:
39
  print(message)
 
 
 
 
 
 
 
40
 
 
 
 
 
 
 
 
 
41
  @st.cache_data
42
  def convert_df(df):
43
  return df.to_csv(index=False).encode('utf-8')
@@ -66,13 +82,27 @@ def save_data(
66
  scheduler.append(data)
67
 
68
  def processFile(filePath):
 
69
  global gainWindow
70
  global minimumGain
71
  global maximumGain
72
  print("Loading file")
73
  waveformList, sampleRate = su.splitIntoTimeSegments(filePath,600)
74
  print("File loaded")
75
- waveformEnhanced = su.combineWaveforms(waveformList)
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  print("Equalizing Audio")
77
  waveform_gain_adjusted = su.equalizeVolume()(waveformEnhanced,sampleRate,gainWindow,minimumGain,maximumGain)
78
  if (earlyCleanup):
@@ -128,7 +158,7 @@ def updateCategoryOptions(resultIndex):
128
  #st.info(f"After update: {st.session_state.categorySelect}")
129
 
130
  def updateMultiSelect():
131
- currFileIndex = file_names.index(st.session_state["select_currFile"])
132
  st.session_state.resetResult = True
133
  for i, category in enumerate(st.session_state['categories']):
134
  st.session_state[f'multiselect_{category}'] = st.session_state['categorySelect'][currFileIndex][i]
@@ -168,92 +198,113 @@ def analyze(inFileName):
168
  st.session_state.summaries[currFileIndex]["df3"] = df3
169
  printV(f'Set df3',4)
170
 
171
- df4_dict = {}
172
  nameList = st.session_state.categories
173
  extraNames = []
174
  valueList = [0 for i in range(len(nameList))]
175
  extraValues = []
176
-
177
  for sp in speakerNames:
178
  foundSp = False
179
  for i, categoryName in enumerate(nameList):
180
  if sp in categorySelections[i]:
181
- #st.info(categoryName)
182
  valueList[i] += su.sumTimes(currAnnotation.subset([sp]))
183
  foundSp = True
184
  break
185
- if foundSp:
186
- continue
187
- else:
188
  extraNames.append(sp)
189
  extraValues.append(su.sumTimes(currAnnotation.subset([sp])))
190
- extraPairsSorted = sorted(zip(extraNames, extraValues), key=lambda pair: pair[0])
191
- extraNames, extraValues = zip(*extraPairsSorted)
 
 
 
 
 
 
 
192
  df4_dict = {
193
- "values": valueList+list(extraValues),
194
- "names": nameList+list(extraNames),
195
- }
196
  df4 = pd.DataFrame(data=df4_dict)
197
  df4.name = "df4"
198
  st.session_state.summaries[currFileIndex]["df4"] = df4
 
199
 
200
- printV(f'Set df4',4)
201
-
202
- speakerList,timeList = su.sumTimesPerSpeaker(oneVoice)
203
  multiSpeakerList, multiTimeList = su.sumMultiTimesPerSpeaker(multiVoice)
204
- summativeMultiSpeaker = sum(multiTimeList)
205
- basePercentiles = [sumNoVoice/currTotalTime,
206
- sumOneVoice/currTotalTime,
207
- sumMultiVoice/currTotalTime
208
- ]
209
- df5 = pd.DataFrame(
210
- {
211
- "ids" : ["NV","OV","MV"]+[f"OV_{i}" for i in range(len(speakerList))]
212
- +[f"MV_{i}" for i in range(len(multiSpeakerList))],
213
- "labels" : ["No Voice","One Voice","Multi Voice"] + speakerList + multiSpeakerList,
214
- "parents" : ["","",""]+["OV" for i in range(len(speakerList))]
215
- +["MV" for i in range(len(multiSpeakerList))],
216
- "parentNames" : ["Total","Total","Total"]+["One Voice" for i in range(len(speakerList))]
217
- +["Multi Voice" for i in range(len(multiSpeakerList))],
218
- "values" : [sumNoVoice,
219
- sumOneVoice,
220
- sumMultiVoice,
221
- ] + timeList + multiTimeList,
222
- "valueStrings" : [su.timeToString(sumNoVoice),
223
- su.timeToString(sumOneVoice),
224
- su.timeToString(sumMultiVoice),
225
- ] + su.timeToString(timeList) + su.timeToString(multiTimeList),
226
- "percentiles" : [basePercentiles[0]*100,
227
- basePercentiles[1]*100,
228
- basePercentiles[2]*100] +
229
- [(t*100) / sumOneVoice * basePercentiles[1] for t in timeList] +
230
- [(t*100) / summativeMultiSpeaker * basePercentiles[2] for t in multiTimeList],
231
- "parentPercentiles" : [basePercentiles[0]*100,
232
- basePercentiles[1]*100,
233
- basePercentiles[2]*100] +
234
- [(t*100) / sumOneVoice for t in timeList] +
235
- [(t*100) / summativeMultiSpeaker for t in multiTimeList],
236
-
237
- }
238
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  df5.name = "df5"
240
  st.session_state.summaries[currFileIndex]["df5"] = df5
241
- printV(f'Set df5',4)
242
-
243
- speakers_dataFrame,speakers_times = su.annotationToDataFrame(currAnnotation)
 
244
  st.session_state.summaries[currFileIndex]["speakers_dataFrame"] = speakers_dataFrame
245
  st.session_state.summaries[currFileIndex]["speakers_times"] = speakers_times
246
 
247
  df2_dict = {
248
- "values":[100*t/currTotalTime for t in df4_dict["values"]],
249
- "names":df4_dict["names"]
250
  }
251
  df2 = pd.DataFrame(df2_dict)
252
  st.session_state.summaries[currFileIndex]["df2"] = df2
253
- printV(f'Set df2',4)
254
- except ValueError as e:
255
- print(f"Value Error: {e}")
256
- pass
 
 
257
 
258
  #----------------------------------------------------------------------------------------------------------------------
259
 
@@ -271,6 +322,7 @@ secondDifference = 5
271
  gainWindow = 4
272
  minimumGain = -45
273
  maximumGain = -5
 
274
 
275
  isGPU = False
276
 
@@ -287,6 +339,10 @@ except RuntimeError as e:
287
  print(f"Using {device} instead.")
288
  #device = xm.xla_device()
289
 
 
 
 
 
290
  pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1")
291
  pipeline.to(device)#torch.device("cuda"))
292
 
@@ -294,6 +350,8 @@ pipeline.to(device)#torch.device("cuda"))
294
  # Long-range usage
295
  if 'results' not in st.session_state:
296
  st.session_state.results = []
 
 
297
  if 'summaries' not in st.session_state:
298
  st.session_state.summaries = []
299
  if 'categories' not in st.session_state:
@@ -367,6 +425,8 @@ if uploaded_file_paths is not None:
367
  st.session_state.categorySelect.append(tempCategories)
368
  while (len(st.session_state.summaries) < len(valid_files)):
369
  st.session_state.summaries.append([])
 
 
370
 
371
  st.session_state.file_names = file_names
372
 
@@ -473,6 +533,8 @@ if st.sidebar.button("Load Demo Example"):
473
  st.session_state.categorySelect.append(tempCategories)
474
  while (len(st.session_state.summaries) < len(valid_files)):
475
  st.session_state.summaries.append([])
 
 
476
 
477
  with st.spinner(text=f'Loading Demo Sample'):
478
  # RTTM load as filler
@@ -484,6 +546,8 @@ if st.sidebar.button("Load Demo Example"):
484
  totalSeconds = segment.end
485
  st.session_state.results = [(annotations, totalSeconds)]
486
  st.session_state.summaries = [{}]
 
 
487
  speakerNames = annotations.labels()
488
  st.session_state.unusedSpeakers = [speakerNames]
489
  with st.spinner(text=f'Analyzing Demo Data'):
@@ -533,6 +597,23 @@ try:
533
 
534
  newCategory = st.sidebar.text_input('Add category', key='categoryInput',on_change=addCategory)
535
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  catTypeColors = su.colorsCSS(3)
537
  allColors = su.colorsCSS(len(speakerNames)+len(st.session_state.categories))
538
  speakerColors = allColors[:len(speakerNames)]
@@ -561,7 +642,8 @@ try:
561
  st.session_state.summaries[currFileIndex]["df4"] = df4
562
 
563
  with dataTab:
564
- csv = convert_df(currDF)
 
565
 
566
  st.download_button(
567
  "Press to Download analysis data",
@@ -571,7 +653,7 @@ try:
571
  key='download-csv',
572
  on_click="ignore",
573
  )
574
- st.dataframe(currDF)
575
  with pie1:
576
  printV("In Pie1",4)
577
  df3 = st.session_state.summaries[currFileIndex]["df3"]
@@ -585,46 +667,52 @@ try:
585
  printV("Pie1 Pretrace",4)
586
  fig1.add_trace(go.Pie(values=df3["values"],labels=df3["names"],sort=False))
587
  printV("Pie1 Posttrace",4)
588
-
589
  col1_1, col1_2 = st.columns(2)
590
- fig1.write_image("ascn_pie1.pdf")
591
- fig1.write_image("ascn_pie1.svg")
 
 
 
592
  printV("Pie1 files written",4)
593
  with col1_1:
594
- printV("Pie1 in col1_1",4)
595
- with open('ascn_pie1.pdf','rb') as f:
596
- printV("Pie1 in file open",4)
597
- st.download_button(
598
- "Save As PDF",
599
- f,
600
- 'sonogram-voice-category-'+currPlainName+'.pdf',
601
- 'application/pdf',
602
- key='download-pdf1',
603
- on_click="ignore",
604
- )
605
- printV("Pie1 after col1_1",4)
 
606
  with col1_2:
607
- with open('ascn_pie1.svg','rb') as f:
608
- st.download_button(
609
- "Save As SVG",
610
- f,
611
- 'sonogram-voice-category-'+currPlainName+'.svg',
612
- 'image/svg+xml',
613
- key='download-svg1',
614
- on_click="ignore",
615
- )
616
- printV("Pie1 in col1_2",4)
617
- st.plotly_chart(fig1, use_container_width=True,config=config)
618
  printV("Pie1 post plotly",4)
619
 
620
  with pie2:
621
- df4 = st.session_state.summaries[currFileIndex]["df4"]
 
622
 
623
  # Some speakers may be missing, so fix colors
624
  figColors = []
625
  for n in df4["names"]:
626
  if n in speakerNames:
627
  figColors.append(speakerColors[speakerNames.index(n)])
 
628
  fig2 = go.Figure()
629
  fig2.update_layout(
630
  title_text="Percentage of Speakers and Custom Categories",
@@ -632,35 +720,43 @@ try:
632
  plot_bgcolor='rgba(0, 0, 0, 0)',
633
  paper_bgcolor='rgba(0, 0, 0, 0)',
634
  )
 
635
  fig2.add_trace(go.Pie(values=df4["values"],labels=df4["names"],sort=False))
636
-
 
637
  col2_1, col2_2 = st.columns(2)
638
- fig2.write_image("ascn_pie2.pdf")
639
- fig2.write_image("ascn_pie2.svg")
 
 
 
640
  with col2_1:
641
- with open('ascn_pie2.pdf','rb') as f:
642
- st.download_button(
643
- "Save As PDF",
644
- f,
645
- 'sonogram-speaker-percent-'+currPlainName+'.pdf',
646
- 'application/pdf',
647
- key='download-pdf2',
648
- on_click="ignore",
649
- )
 
650
  with col2_2:
651
- with open('ascn_pie2.svg','rb') as f:
652
- st.download_button(
653
- "Save As SVG",
654
- f,
655
- 'sonogram-speaker-percent-'+currPlainName+'.svg',
656
- 'image/svg+xml',
657
- key='download-svg2',
658
- on_click="ignore",
659
- )
660
- st.plotly_chart(fig2, use_container_width=True,config=config)
661
 
662
  with sunburst1:
663
- df5 = st.session_state.summaries[currFileIndex]["df5"]
 
 
664
  fig3_1 = px.sunburst(df5,
665
  branchvalues = 'total',
666
  names = "labels",
@@ -685,34 +781,40 @@ try:
685
  plot_bgcolor='rgba(0, 0, 0, 0)',
686
  paper_bgcolor='rgba(0, 0, 0, 0)',
687
  )
688
-
689
  col3_1, col3_2 = st.columns(2)
690
- fig3_1.write_image("ascn_sunburst.pdf")
691
- fig3_1.write_image("ascn_sunburst.svg")
 
 
 
692
  with col3_1:
693
- with open('ascn_sunburst.pdf','rb') as f:
694
- st.download_button(
695
- "Save As PDF",
696
- f,
697
- 'sonogram-speaker-categories-'+currPlainName+'.pdf',
698
- 'application/pdf',
699
- key='download-pdf3',
700
- on_click="ignore",
701
- )
 
702
  with col3_2:
703
- with open('ascn_sunburst.svg','rb') as f:
704
- st.download_button(
705
- "Save As SVG",
706
- f,
707
- 'sonogram-speaker-categories-'+currPlainName+'.svg',
708
- 'image/svg+xml',
709
- key='download-svg3',
710
- on_click="ignore",
711
- )
712
- st.plotly_chart(fig3_1, use_container_width=True,config=config)
713
 
714
  with treemap1:
715
- df5 = st.session_state.summaries[currFileIndex]["df5"]
 
 
716
  fig3 = px.treemap(df5,
717
  branchvalues = "total",
718
  names = "labels",
@@ -737,37 +839,43 @@ try:
737
  plot_bgcolor='rgba(0, 0, 0, 0)',
738
  paper_bgcolor='rgba(0, 0, 0, 0)',
739
  )
740
-
741
  col4_1, col4_2 = st.columns(2)
742
- fig3.write_image("ascn_treemap.pdf")
743
- fig3.write_image("ascn_treemap.svg")
 
 
 
744
  with col4_1:
745
- with open('ascn_treemap.pdf','rb') as f:
746
- st.download_button(
747
- "Save As PDF",
748
- f,
749
- 'sonogram-treemap-'+currPlainName+'.pdf',
750
- 'application/pdf',
751
- key='download-pdf4',
752
- on_click="ignore",
753
- )
 
754
  with col4_2:
755
- with open('ascn_treemap.svg','rb') as f:
756
- st.download_button(
757
- "Save As SVG",
758
- f,
759
- 'sonogram-treemap-'+currPlainName+'.svg',
760
- 'image/svg+xml',
761
- key='download-svg4',
762
- on_click="ignore",
763
- )
764
- st.plotly_chart(fig3, use_container_width=True,config=config)
765
 
766
  # generate plotting window
767
 
768
 
769
  with timeline:
770
- fig_la = px.timeline(speakers_dataFrame, x_start="Start", x_end="Finish", y="Resource", color="Resource",title="Timeline of Audio with Speakers",
 
 
771
  color_discrete_sequence=speakerColors)
772
  fig_la.update_yaxes(autorange="reversed")
773
 
@@ -793,34 +901,39 @@ try:
793
  legend={'traceorder':'reversed'},
794
  yaxis= {'showticklabels': False},
795
  )
796
-
797
  col5_1, col5_2 = st.columns(2)
798
- fig_la.write_image("ascn_timeline.pdf")
799
- fig_la.write_image("ascn_timeline.svg")
 
 
 
800
  with col5_1:
801
- with open('ascn_timeline.pdf','rb') as f:
802
- st.download_button(
803
- "Save As PDF",
804
- f,
805
- 'sonogram-timeline-'+currPlainName+'.pdf',
806
- 'application/pdf',
807
- key='download-pdf5',
808
- on_click="ignore",
809
- )
 
810
  with col5_2:
811
- with open('ascn_timeline.svg','rb') as f:
812
- st.download_button(
813
- "Save As SVG",
814
- f,
815
- 'sonogram-timeline-'+currPlainName+'.svg',
816
- 'image/svg+xml',
817
- key='download-svg5',
818
- on_click="ignore",
819
- )
820
- st.plotly_chart(fig_la, use_container_width=True,config=config)
821
 
822
  with bar1:
823
- df2 = st.session_state.summaries[currFileIndex]["df2"]
 
824
  fig2_la = px.bar(df2, x="values", y="names", color="names", orientation='h',
825
  custom_data=["names","values"],title="Time Spoken by each Speaker",
826
  color_discrete_sequence=catColors+speakerColors)
@@ -841,31 +954,35 @@ try:
841
  'Percentage of Time: %{customdata[1]:.2f}%'
842
  ])
843
  )
844
-
845
  col6_1, col6_2 = st.columns(2)
846
- fig_la.write_image("ascn_bar.pdf")
847
- fig_la.write_image("ascn_bar.svg")
 
 
 
848
  with col6_1:
849
- with open('ascn_bar.pdf','rb') as f:
850
- st.download_button(
851
- "Save As PDF",
852
- f,
853
- 'sonogram-speaker-time-'+currPlainName+'.pdf',
854
- 'application/pdf',
855
- key='download-pdf6',
856
- on_click="ignore",
857
- )
 
858
  with col6_2:
859
- with open('ascn_bar.svg','rb') as f:
860
- st.download_button(
861
- "Save As SVG",
862
- f,
863
- 'sonogram-speaker-time-'+currPlainName+'.svg',
864
- 'image/svg+xml',
865
- key='download-svg6',
866
- on_click="ignore",
867
- )
868
- st.plotly_chart(fig2_la, use_container_width=True,config=config)
869
 
870
  except ValueError:
871
  pass
 
22
  from pyannote.core import Annotation, Segment, Timeline
23
  import datetime as dt
24
 
25
+ enableDenoise = False
26
  earlyCleanup = True
27
 
28
  # [None,Low,Medium,High,Debug]
 
38
  global verbosity
39
  if verbosity>=verbosityLevel:
40
  print(message)
41
+
42
+ def get_display_name(speaker, fileIndex):
43
+ """Return the user-assigned display name for a speaker, or the original label."""
44
+ renames = st.session_state.speakerRenames
45
+ if fileIndex < len(renames) and speaker in renames[fileIndex]:
46
+ return renames[fileIndex][speaker]
47
+ return speaker
48
 
49
+ def apply_speaker_renames_to_df(df, fileIndex, column="task"):
50
+ """Replace speaker_## labels in a DataFrame column with display names."""
51
+ if column not in df.columns:
52
+ return df
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')
 
82
  scheduler.append(data)
83
 
84
  def processFile(filePath):
85
+ global attenLimDb
86
  global gainWindow
87
  global minimumGain
88
  global maximumGain
89
  print("Loading file")
90
  waveformList, sampleRate = su.splitIntoTimeSegments(filePath,600)
91
  print("File loaded")
92
+ enhancedWaveformList = []
93
+ if (enableDenoise):
94
+ print("Denoising")
95
+ for w in waveformList:
96
+ if (enableDenoise):
97
+ newW = enhance(dfModel,dfState,w,atten_lim_db=attenLimDB).detach().cpu()
98
+ enhancedWaveformList.append(newW)
99
+ else:
100
+ enhancedWaveformList.append(w)
101
+ if (enableDenoise):
102
+ print("Audio denoised")
103
+ waveformEnhanced = su.combineWaveforms(enhancedWaveformList)
104
+ if (earlyCleanup):
105
+ del enhancedWaveformList
106
  print("Equalizing Audio")
107
  waveform_gain_adjusted = su.equalizeVolume()(waveformEnhanced,sampleRate,gainWindow,minimumGain,maximumGain)
108
  if (earlyCleanup):
 
158
  #st.info(f"After update: {st.session_state.categorySelect}")
159
 
160
  def updateMultiSelect():
161
+ currFileIndex = st.session_state.file_names.index(st.session_state["select_currFile"])
162
  st.session_state.resetResult = True
163
  for i, category in enumerate(st.session_state['categories']):
164
  st.session_state[f'multiselect_{category}'] = st.session_state['categorySelect'][currFileIndex][i]
 
198
  st.session_state.summaries[currFileIndex]["df3"] = df3
199
  printV(f'Set df3',4)
200
 
201
+ # --- Build df4 ---
202
  nameList = st.session_state.categories
203
  extraNames = []
204
  valueList = [0 for i in range(len(nameList))]
205
  extraValues = []
206
+
207
  for sp in speakerNames:
208
  foundSp = False
209
  for i, categoryName in enumerate(nameList):
210
  if sp in categorySelections[i]:
 
211
  valueList[i] += su.sumTimes(currAnnotation.subset([sp]))
212
  foundSp = True
213
  break
214
+ if not foundSp:
 
 
215
  extraNames.append(sp)
216
  extraValues.append(su.sumTimes(currAnnotation.subset([sp])))
217
+
218
+ if extraNames:
219
+ extraPairsSorted = sorted(zip(extraNames, extraValues), key=lambda pair: pair[0])
220
+ extraNames, extraValues = list(zip(*extraPairsSorted))
221
+ extraNames = list(extraNames)
222
+ extraValues = list(extraValues)
223
+ else:
224
+ extraNames, extraValues = [], []
225
+
226
  df4_dict = {
227
+ "values": valueList + extraValues,
228
+ "names": nameList + extraNames,
229
+ }
230
  df4 = pd.DataFrame(data=df4_dict)
231
  df4.name = "df4"
232
  st.session_state.summaries[currFileIndex]["df4"] = df4
233
+ printV(f'Set df4', 4)
234
 
235
+ # --- Build df5 ---
236
+ speakerList, timeList = su.sumTimesPerSpeaker(oneVoice)
 
237
  multiSpeakerList, multiTimeList = su.sumMultiTimesPerSpeaker(multiVoice)
238
+
239
+ speakerList = list(speakerList) if speakerList else []
240
+ timeList = list(timeList) if timeList else []
241
+ multiSpeakerList = list(multiSpeakerList) if multiSpeakerList else []
242
+ multiTimeList = list(multiTimeList) if multiTimeList else []
243
+
244
+ summativeMultiSpeaker = sum(multiTimeList) if multiTimeList else 1
245
+ safeOneVoice = sumOneVoice if sumOneVoice > 0 else 1
246
+
247
+ basePercentiles = [
248
+ sumNoVoice / currTotalTime,
249
+ sumOneVoice / currTotalTime,
250
+ sumMultiVoice / currTotalTime,
251
+ ]
252
+
253
+ timeStrings = su.timeToString(timeList) if timeList else []
254
+ multiTimeStrings = su.timeToString(multiTimeList) if multiTimeList else []
255
+ if isinstance(timeStrings, str):
256
+ timeStrings = [timeStrings]
257
+ if isinstance(multiTimeStrings, str):
258
+ multiTimeStrings = [multiTimeStrings]
259
+
260
+ n_ov = len(speakerList)
261
+ n_mv = len(multiSpeakerList)
262
+
263
+ df5 = pd.DataFrame({
264
+ "ids": ["NV", "OV", "MV"] + [f"OV_{i}" for i in range(n_ov)] + [f"MV_{i}" for i in range(n_mv)],
265
+ "labels": ["No Voice", "One Voice", "Multi Voice"] + speakerList + multiSpeakerList,
266
+ "parents": ["", "", ""] + ["OV"] * n_ov + ["MV"] * n_mv,
267
+ "parentNames": ["Total", "Total", "Total"] + ["One Voice"] * n_ov + ["Multi Voice"] * n_mv,
268
+ "values": [sumNoVoice, sumOneVoice, sumMultiVoice] + timeList + multiTimeList,
269
+ "valueStrings": [
270
+ su.timeToString(sumNoVoice),
271
+ su.timeToString(sumOneVoice),
272
+ su.timeToString(sumMultiVoice),
273
+ ] + timeStrings + multiTimeStrings,
274
+ "percentiles": [
275
+ basePercentiles[0] * 100,
276
+ basePercentiles[1] * 100,
277
+ basePercentiles[2] * 100,
278
+ ] + [(t * 100) / safeOneVoice * basePercentiles[1] for t in timeList]
279
+ + [(t * 100) / summativeMultiSpeaker * basePercentiles[2] for t in multiTimeList],
280
+ "parentPercentiles": [
281
+ basePercentiles[0] * 100,
282
+ basePercentiles[1] * 100,
283
+ basePercentiles[2] * 100,
284
+ ] + [(t * 100) / safeOneVoice for t in timeList]
285
+ + [(t * 100) / summativeMultiSpeaker for t in multiTimeList],
286
+ })
287
  df5.name = "df5"
288
  st.session_state.summaries[currFileIndex]["df5"] = df5
289
+ printV(f'Set df5', 4)
290
+
291
+ # --- Build speakers_dataFrame, df2 ---
292
+ speakers_dataFrame, speakers_times = su.annotationToDataFrame(currAnnotation)
293
  st.session_state.summaries[currFileIndex]["speakers_dataFrame"] = speakers_dataFrame
294
  st.session_state.summaries[currFileIndex]["speakers_times"] = speakers_times
295
 
296
  df2_dict = {
297
+ "values": [100 * t / currTotalTime for t in df4_dict["values"]],
298
+ "names": df4_dict["names"],
299
  }
300
  df2 = pd.DataFrame(df2_dict)
301
  st.session_state.summaries[currFileIndex]["df2"] = df2
302
+ printV(f'Set df2', 4)
303
+ except Exception as e:
304
+ import traceback
305
+ print(f"Error in analyze: {e}")
306
+ traceback.print_exc()
307
+ st.error(f"Debug - analyze() failed: {e}")
308
 
309
  #----------------------------------------------------------------------------------------------------------------------
310
 
 
322
  gainWindow = 4
323
  minimumGain = -45
324
  maximumGain = -5
325
+ attenLimDB = 3
326
 
327
  isGPU = False
328
 
 
339
  print(f"Using {device} instead.")
340
  #device = xm.xla_device()
341
 
342
+ if (enableDenoise):
343
+ # Instantiate and prepare model for training.
344
+ dfModel, dfState, _ = init_df(model_base_dir="DeepFilterNet3")
345
+ dfModel.to(device)#torch.device("cuda"))
346
  pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1")
347
  pipeline.to(device)#torch.device("cuda"))
348
 
 
350
  # Long-range usage
351
  if 'results' not in st.session_state:
352
  st.session_state.results = []
353
+ if 'speakerRenames' not in st.session_state:
354
+ st.session_state.speakerRenames = []
355
  if 'summaries' not in st.session_state:
356
  st.session_state.summaries = []
357
  if 'categories' not in st.session_state:
 
425
  st.session_state.categorySelect.append(tempCategories)
426
  while (len(st.session_state.summaries) < len(valid_files)):
427
  st.session_state.summaries.append([])
428
+ while (len(st.session_state.speakerRenames) < len(valid_files)):
429
+ st.session_state.speakerRenames.append({})
430
 
431
  st.session_state.file_names = file_names
432
 
 
533
  st.session_state.categorySelect.append(tempCategories)
534
  while (len(st.session_state.summaries) < len(valid_files)):
535
  st.session_state.summaries.append([])
536
+ while (len(st.session_state.speakerRenames) < len(valid_files)):
537
+ st.session_state.speakerRenames.append({})
538
 
539
  with st.spinner(text=f'Loading Demo Sample'):
540
  # RTTM load as filler
 
546
  totalSeconds = segment.end
547
  st.session_state.results = [(annotations, totalSeconds)]
548
  st.session_state.summaries = [{}]
549
+ while len(st.session_state.speakerRenames) < 1:
550
+ st.session_state.speakerRenames.append({})
551
  speakerNames = annotations.labels()
552
  st.session_state.unusedSpeakers = [speakerNames]
553
  with st.spinner(text=f'Analyzing Demo Data'):
 
597
 
598
  newCategory = st.sidebar.text_input('Add category', key='categoryInput',on_change=addCategory)
599
 
600
+ st.sidebar.divider()
601
+ st.sidebar.subheader("Rename Speakers")
602
+ st.sidebar.caption("Replace SPEAKER_## labels with real names.")
603
+ current_renames = st.session_state.speakerRenames[currFileIndex]
604
+ for sp in speakerNames:
605
+ current_label = current_renames.get(sp, "")
606
+ new_name = st.sidebar.text_input(
607
+ f"{sp}",
608
+ value=current_label,
609
+ placeholder=f"e.g. John",
610
+ key=f"rename_{currFileIndex}_{sp}"
611
+ )
612
+ if new_name.strip():
613
+ st.session_state.speakerRenames[currFileIndex][sp] = new_name.strip()
614
+ elif sp in st.session_state.speakerRenames[currFileIndex]:
615
+ del st.session_state.speakerRenames[currFileIndex][sp]
616
+
617
  catTypeColors = su.colorsCSS(3)
618
  allColors = su.colorsCSS(len(speakerNames)+len(st.session_state.categories))
619
  speakerColors = allColors[:len(speakerNames)]
 
642
  st.session_state.summaries[currFileIndex]["df4"] = df4
643
 
644
  with dataTab:
645
+ displayDF = apply_speaker_renames_to_df(currDF, currFileIndex, column="Resource")
646
+ csv = convert_df(displayDF)
647
 
648
  st.download_button(
649
  "Press to Download analysis data",
 
653
  key='download-csv',
654
  on_click="ignore",
655
  )
656
+ st.dataframe(displayDF)
657
  with pie1:
658
  printV("In Pie1",4)
659
  df3 = st.session_state.summaries[currFileIndex]["df3"]
 
667
  printV("Pie1 Pretrace",4)
668
  fig1.add_trace(go.Pie(values=df3["values"],labels=df3["names"],sort=False))
669
  printV("Pie1 Posttrace",4)
670
+ st.plotly_chart(fig1, use_container_width=True, config=config)
671
  col1_1, col1_2 = st.columns(2)
672
+ try:
673
+ fig1.write_image("ascn_pie1.pdf")
674
+ fig1.write_image("ascn_pie1.svg")
675
+ except Exception:
676
+ pass
677
  printV("Pie1 files written",4)
678
  with col1_1:
679
+ if os.path.exists('ascn_pie1.pdf'):
680
+ printV("Pie1 in col1_1",4)
681
+ with open('ascn_pie1.pdf','rb') as f:
682
+ printV("Pie1 in file open",4)
683
+ st.download_button(
684
+ "Save As PDF",
685
+ f,
686
+ 'sonogram-voice-category-'+currPlainName+'.pdf',
687
+ 'application/pdf',
688
+ key='download-pdf1',
689
+ on_click="ignore",
690
+ )
691
+ printV("Pie1 after col1_1",4)
692
  with col1_2:
693
+ if os.path.exists('ascn_pie1.svg'):
694
+ with open('ascn_pie1.svg','rb') as f:
695
+ st.download_button(
696
+ "Save As SVG",
697
+ f,
698
+ 'sonogram-voice-category-'+currPlainName+'.svg',
699
+ 'image/svg+xml',
700
+ key='download-svg1',
701
+ on_click="ignore",
702
+ )
703
+ printV("Pie1 in col1_2",4)
704
  printV("Pie1 post plotly",4)
705
 
706
  with pie2:
707
+ printV("In Pie2",4)
708
+ df4 = st.session_state.summaries[currFileIndex]["df4"].copy()
709
 
710
  # Some speakers may be missing, so fix colors
711
  figColors = []
712
  for n in df4["names"]:
713
  if n in speakerNames:
714
  figColors.append(speakerColors[speakerNames.index(n)])
715
+ df4["names"] = df4["names"].apply(lambda s: get_display_name(s, currFileIndex))
716
  fig2 = go.Figure()
717
  fig2.update_layout(
718
  title_text="Percentage of Speakers and Custom Categories",
 
720
  plot_bgcolor='rgba(0, 0, 0, 0)',
721
  paper_bgcolor='rgba(0, 0, 0, 0)',
722
  )
723
+ printV("Pie2 Pretrace",4)
724
  fig2.add_trace(go.Pie(values=df4["values"],labels=df4["names"],sort=False))
725
+ printV("Pie2 Posttrace",4)
726
+ st.plotly_chart(fig2, use_container_width=True, config=config)
727
  col2_1, col2_2 = st.columns(2)
728
+ try:
729
+ fig2.write_image("ascn_pie2.pdf")
730
+ fig2.write_image("ascn_pie2.svg")
731
+ except Exception:
732
+ pass
733
  with col2_1:
734
+ if os.path.exists('ascn_pie2.pdf'):
735
+ with open('ascn_pie2.pdf','rb') as f:
736
+ st.download_button(
737
+ "Save As PDF",
738
+ f,
739
+ 'sonogram-speaker-percent-'+currPlainName+'.pdf',
740
+ 'application/pdf',
741
+ key='download-pdf2',
742
+ on_click="ignore",
743
+ )
744
  with col2_2:
745
+ if os.path.exists('ascn_pie2.svg'):
746
+ with open('ascn_pie2.svg','rb') as f:
747
+ st.download_button(
748
+ "Save As SVG",
749
+ f,
750
+ 'sonogram-speaker-percent-'+currPlainName+'.svg',
751
+ 'image/svg+xml',
752
+ key='download-svg2',
753
+ on_click="ignore",
754
+ )
755
 
756
  with sunburst1:
757
+ df5 = st.session_state.summaries[currFileIndex]["df5"].copy()
758
+ df5["labels"] = df5["labels"].apply(lambda s: get_display_name(s, currFileIndex))
759
+ df5["parentNames"] = df5["parentNames"].apply(lambda s: get_display_name(s, currFileIndex))
760
  fig3_1 = px.sunburst(df5,
761
  branchvalues = 'total',
762
  names = "labels",
 
781
  plot_bgcolor='rgba(0, 0, 0, 0)',
782
  paper_bgcolor='rgba(0, 0, 0, 0)',
783
  )
784
+ st.plotly_chart(fig3_1, use_container_width=True, config=config)
785
  col3_1, col3_2 = st.columns(2)
786
+ try:
787
+ fig3_1.write_image("ascn_sunburst.pdf")
788
+ fig3_1.write_image("ascn_sunburst.svg")
789
+ except Exception:
790
+ pass
791
  with col3_1:
792
+ if os.path.exists('ascn_sunburst.pdf'):
793
+ with open('ascn_sunburst.pdf','rb') as f:
794
+ st.download_button(
795
+ "Save As PDF",
796
+ f,
797
+ 'sonogram-speaker-categories-'+currPlainName+'.pdf',
798
+ 'application/pdf',
799
+ key='download-pdf3',
800
+ on_click="ignore",
801
+ )
802
  with col3_2:
803
+ if os.path.exists('ascn_sunburst.svg'):
804
+ with open('ascn_sunburst.svg','rb') as f:
805
+ st.download_button(
806
+ "Save As SVG",
807
+ f,
808
+ 'sonogram-speaker-categories-'+currPlainName+'.svg',
809
+ 'image/svg+xml',
810
+ key='download-svg3',
811
+ on_click="ignore",
812
+ )
813
 
814
  with treemap1:
815
+ df5 = st.session_state.summaries[currFileIndex]["df5"].copy()
816
+ df5["labels"] = df5["labels"].apply(lambda s: get_display_name(s, currFileIndex))
817
+ df5["parentNames"] = df5["parentNames"].apply(lambda s: get_display_name(s, currFileIndex))
818
  fig3 = px.treemap(df5,
819
  branchvalues = "total",
820
  names = "labels",
 
839
  plot_bgcolor='rgba(0, 0, 0, 0)',
840
  paper_bgcolor='rgba(0, 0, 0, 0)',
841
  )
842
+ st.plotly_chart(fig3, use_container_width=True, config=config)
843
  col4_1, col4_2 = st.columns(2)
844
+ try:
845
+ fig3.write_image("ascn_treemap.pdf")
846
+ fig3.write_image("ascn_treemap.svg")
847
+ except Exception:
848
+ pass
849
  with col4_1:
850
+ if os.path.exists('ascn_treemap.pdf'):
851
+ with open('ascn_treemap.pdf','rb') as f:
852
+ st.download_button(
853
+ "Save As PDF",
854
+ f,
855
+ 'sonogram-treemap-'+currPlainName+'.pdf',
856
+ 'application/pdf',
857
+ key='download-pdf4',
858
+ on_click="ignore",
859
+ )
860
  with col4_2:
861
+ if os.path.exists('ascn_treemap.svg'):
862
+ with open('ascn_treemap.svg','rb') as f:
863
+ st.download_button(
864
+ "Save As SVG",
865
+ f,
866
+ 'sonogram-treemap-'+currPlainName+'.svg',
867
+ 'image/svg+xml',
868
+ key='download-svg4',
869
+ on_click="ignore",
870
+ )
871
 
872
  # generate plotting window
873
 
874
 
875
  with timeline:
876
+ timeline_df = speakers_dataFrame.copy()
877
+ timeline_df["Resource"] = timeline_df["Resource"].apply(lambda s: get_display_name(s, currFileIndex))
878
+ fig_la = px.timeline(timeline_df, x_start="Start", x_end="Finish", y="Resource", color="Resource",title="Timeline of Audio with Speakers",
879
  color_discrete_sequence=speakerColors)
880
  fig_la.update_yaxes(autorange="reversed")
881
 
 
901
  legend={'traceorder':'reversed'},
902
  yaxis= {'showticklabels': False},
903
  )
904
+ st.plotly_chart(fig_la, use_container_width=True, config=config)
905
  col5_1, col5_2 = st.columns(2)
906
+ try:
907
+ fig_la.write_image("ascn_timeline.pdf")
908
+ fig_la.write_image("ascn_timeline.svg")
909
+ except Exception:
910
+ pass
911
  with col5_1:
912
+ if os.path.exists('ascn_timeline.pdf'):
913
+ with open('ascn_timeline.pdf','rb') as f:
914
+ st.download_button(
915
+ "Save As PDF",
916
+ f,
917
+ 'sonogram-timeline-'+currPlainName+'.pdf',
918
+ 'application/pdf',
919
+ key='download-pdf5',
920
+ on_click="ignore",
921
+ )
922
  with col5_2:
923
+ if os.path.exists('ascn_timeline.svg'):
924
+ with open('ascn_timeline.svg','rb') as f:
925
+ st.download_button(
926
+ "Save As SVG",
927
+ f,
928
+ 'sonogram-timeline-'+currPlainName+'.svg',
929
+ 'image/svg+xml',
930
+ key='download-svg5',
931
+ on_click="ignore",
932
+ )
933
 
934
  with bar1:
935
+ df2 = st.session_state.summaries[currFileIndex]["df2"].copy()
936
+ df2["names"] = df2["names"].apply(lambda s: get_display_name(s, currFileIndex))
937
  fig2_la = px.bar(df2, x="values", y="names", color="names", orientation='h',
938
  custom_data=["names","values"],title="Time Spoken by each Speaker",
939
  color_discrete_sequence=catColors+speakerColors)
 
954
  'Percentage of Time: %{customdata[1]:.2f}%'
955
  ])
956
  )
957
+ st.plotly_chart(fig2_la, use_container_width=True, config=config)
958
  col6_1, col6_2 = st.columns(2)
959
+ try:
960
+ fig_la.write_image("ascn_bar.pdf")
961
+ fig_la.write_image("ascn_bar.svg")
962
+ except Exception:
963
+ pass
964
  with col6_1:
965
+ if os.path.exists('ascn_bar.pdf'):
966
+ with open('ascn_bar.pdf','rb') as f:
967
+ st.download_button(
968
+ "Save As PDF",
969
+ f,
970
+ 'sonogram-speaker-time-'+currPlainName+'.pdf',
971
+ 'application/pdf',
972
+ key='download-pdf6',
973
+ on_click="ignore",
974
+ )
975
  with col6_2:
976
+ if os.path.exists('ascn_bar.svg'):
977
+ with open('ascn_bar.svg','rb') as f:
978
+ st.download_button(
979
+ "Save As SVG",
980
+ f,
981
+ 'sonogram-speaker-time-'+currPlainName+'.svg',
982
+ 'image/svg+xml',
983
+ key='download-svg6',
984
+ on_click="ignore",
985
+ )
986
 
987
  except ValueError:
988
  pass