birdnet-analyzer 2.0.0__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. birdnet_analyzer/__init__.py +9 -8
  2. birdnet_analyzer/analyze/__init__.py +5 -5
  3. birdnet_analyzer/analyze/__main__.py +3 -4
  4. birdnet_analyzer/analyze/cli.py +25 -25
  5. birdnet_analyzer/analyze/core.py +241 -245
  6. birdnet_analyzer/analyze/utils.py +692 -701
  7. birdnet_analyzer/audio.py +368 -372
  8. birdnet_analyzer/cli.py +709 -707
  9. birdnet_analyzer/config.py +242 -242
  10. birdnet_analyzer/eBird_taxonomy_codes_2021E.json +25279 -25279
  11. birdnet_analyzer/embeddings/__init__.py +3 -4
  12. birdnet_analyzer/embeddings/__main__.py +3 -3
  13. birdnet_analyzer/embeddings/cli.py +12 -13
  14. birdnet_analyzer/embeddings/core.py +69 -70
  15. birdnet_analyzer/embeddings/utils.py +179 -193
  16. birdnet_analyzer/evaluation/__init__.py +196 -195
  17. birdnet_analyzer/evaluation/__main__.py +3 -3
  18. birdnet_analyzer/evaluation/assessment/__init__.py +0 -0
  19. birdnet_analyzer/evaluation/assessment/metrics.py +388 -0
  20. birdnet_analyzer/evaluation/assessment/performance_assessor.py +409 -0
  21. birdnet_analyzer/evaluation/assessment/plotting.py +379 -0
  22. birdnet_analyzer/evaluation/preprocessing/__init__.py +0 -0
  23. birdnet_analyzer/evaluation/preprocessing/data_processor.py +631 -0
  24. birdnet_analyzer/evaluation/preprocessing/utils.py +98 -0
  25. birdnet_analyzer/gui/__init__.py +19 -23
  26. birdnet_analyzer/gui/__main__.py +3 -3
  27. birdnet_analyzer/gui/analysis.py +175 -174
  28. birdnet_analyzer/gui/assets/arrow_down.svg +4 -4
  29. birdnet_analyzer/gui/assets/arrow_left.svg +4 -4
  30. birdnet_analyzer/gui/assets/arrow_right.svg +4 -4
  31. birdnet_analyzer/gui/assets/arrow_up.svg +4 -4
  32. birdnet_analyzer/gui/assets/gui.css +28 -28
  33. birdnet_analyzer/gui/assets/gui.js +93 -93
  34. birdnet_analyzer/gui/embeddings.py +619 -620
  35. birdnet_analyzer/gui/evaluation.py +795 -813
  36. birdnet_analyzer/gui/localization.py +75 -68
  37. birdnet_analyzer/gui/multi_file.py +245 -246
  38. birdnet_analyzer/gui/review.py +519 -527
  39. birdnet_analyzer/gui/segments.py +191 -191
  40. birdnet_analyzer/gui/settings.py +128 -129
  41. birdnet_analyzer/gui/single_file.py +267 -269
  42. birdnet_analyzer/gui/species.py +95 -95
  43. birdnet_analyzer/gui/train.py +696 -698
  44. birdnet_analyzer/gui/utils.py +810 -808
  45. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_af.txt +6522 -6522
  46. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ar.txt +6522 -6522
  47. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_bg.txt +6522 -6522
  48. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ca.txt +6522 -6522
  49. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_cs.txt +6522 -6522
  50. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_da.txt +6522 -6522
  51. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_de.txt +6522 -6522
  52. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_el.txt +6522 -6522
  53. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_en_uk.txt +6522 -6522
  54. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_es.txt +6522 -6522
  55. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_fi.txt +6522 -6522
  56. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_fr.txt +6522 -6522
  57. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_he.txt +6522 -6522
  58. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_hr.txt +6522 -6522
  59. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_hu.txt +6522 -6522
  60. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_in.txt +6522 -6522
  61. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_is.txt +6522 -6522
  62. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_it.txt +6522 -6522
  63. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ja.txt +6522 -6522
  64. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ko.txt +6522 -6522
  65. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_lt.txt +6522 -6522
  66. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ml.txt +6522 -6522
  67. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_nl.txt +6522 -6522
  68. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_no.txt +6522 -6522
  69. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pl.txt +6522 -6522
  70. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pt_BR.txt +6522 -6522
  71. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_pt_PT.txt +6522 -6522
  72. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ro.txt +6522 -6522
  73. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_ru.txt +6522 -6522
  74. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sk.txt +6522 -6522
  75. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sl.txt +6522 -6522
  76. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sr.txt +6522 -6522
  77. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_sv.txt +6522 -6522
  78. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_th.txt +6522 -6522
  79. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_tr.txt +6522 -6522
  80. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_uk.txt +6522 -6522
  81. birdnet_analyzer/labels/V2.4/BirdNET_GLOBAL_6K_V2.4_Labels_zh.txt +6522 -6522
  82. birdnet_analyzer/lang/de.json +334 -334
  83. birdnet_analyzer/lang/en.json +334 -334
  84. birdnet_analyzer/lang/fi.json +334 -334
  85. birdnet_analyzer/lang/fr.json +334 -334
  86. birdnet_analyzer/lang/id.json +334 -334
  87. birdnet_analyzer/lang/pt-br.json +334 -334
  88. birdnet_analyzer/lang/ru.json +334 -334
  89. birdnet_analyzer/lang/se.json +334 -334
  90. birdnet_analyzer/lang/tlh.json +334 -334
  91. birdnet_analyzer/lang/zh_TW.json +334 -334
  92. birdnet_analyzer/model.py +1212 -1243
  93. birdnet_analyzer/playground.py +5 -0
  94. birdnet_analyzer/search/__init__.py +3 -3
  95. birdnet_analyzer/search/__main__.py +3 -3
  96. birdnet_analyzer/search/cli.py +11 -12
  97. birdnet_analyzer/search/core.py +78 -78
  98. birdnet_analyzer/search/utils.py +107 -111
  99. birdnet_analyzer/segments/__init__.py +3 -3
  100. birdnet_analyzer/segments/__main__.py +3 -3
  101. birdnet_analyzer/segments/cli.py +13 -14
  102. birdnet_analyzer/segments/core.py +81 -78
  103. birdnet_analyzer/segments/utils.py +383 -394
  104. birdnet_analyzer/species/__init__.py +3 -3
  105. birdnet_analyzer/species/__main__.py +3 -3
  106. birdnet_analyzer/species/cli.py +13 -14
  107. birdnet_analyzer/species/core.py +35 -35
  108. birdnet_analyzer/species/utils.py +74 -75
  109. birdnet_analyzer/train/__init__.py +3 -3
  110. birdnet_analyzer/train/__main__.py +3 -3
  111. birdnet_analyzer/train/cli.py +13 -14
  112. birdnet_analyzer/train/core.py +113 -113
  113. birdnet_analyzer/train/utils.py +877 -847
  114. birdnet_analyzer/translate.py +133 -104
  115. birdnet_analyzer/utils.py +426 -419
  116. {birdnet_analyzer-2.0.0.dist-info → birdnet_analyzer-2.0.1.dist-info}/METADATA +137 -129
  117. birdnet_analyzer-2.0.1.dist-info/RECORD +125 -0
  118. {birdnet_analyzer-2.0.0.dist-info → birdnet_analyzer-2.0.1.dist-info}/WHEEL +1 -1
  119. {birdnet_analyzer-2.0.0.dist-info → birdnet_analyzer-2.0.1.dist-info}/licenses/LICENSE +18 -18
  120. birdnet_analyzer-2.0.0.dist-info/RECORD +0 -117
  121. {birdnet_analyzer-2.0.0.dist-info → birdnet_analyzer-2.0.1.dist-info}/entry_points.txt +0 -0
  122. {birdnet_analyzer-2.0.0.dist-info → birdnet_analyzer-2.0.1.dist-info}/top_level.txt +0 -0
@@ -1,191 +1,191 @@
1
- import concurrent.futures
2
- import os
3
- from functools import partial
4
-
5
- import gradio as gr
6
-
7
- import birdnet_analyzer.config as cfg
8
- import birdnet_analyzer.gui.utils as gu
9
- import birdnet_analyzer.gui.localization as loc
10
-
11
- from birdnet_analyzer.segments.utils import extract_segments
12
-
13
- def extract_segments_wrapper(entry):
14
- return (entry[0][0], extract_segments(entry))
15
-
16
-
17
- @gu.gui_runtime_error_handler
18
- def _extract_segments(
19
- audio_dir, result_dir, output_dir, min_conf, num_seq, audio_speed, seq_length, threads, progress=gr.Progress()
20
- ):
21
- from birdnet_analyzer.segments.utils import parse_folders, parse_files
22
-
23
- gu.validate(audio_dir, loc.localize("validation-no-audio-directory-selected"))
24
-
25
- if not result_dir:
26
- result_dir = audio_dir
27
-
28
- if not output_dir:
29
- output_dir = audio_dir
30
-
31
- if progress is not None:
32
- progress(0, desc=f"{loc.localize('progress-search')} ...")
33
-
34
- # Parse audio and result folders
35
- cfg.FILE_LIST = parse_folders(audio_dir, result_dir)
36
-
37
- # Set output folder
38
- cfg.OUTPUT_PATH = output_dir
39
-
40
- # Set number of threads
41
- cfg.CPU_THREADS = int(threads)
42
-
43
- # Set confidence threshold
44
- cfg.MIN_CONFIDENCE = max(0.01, min(0.99, min_conf))
45
-
46
- # Parse file list and make list of segments
47
- cfg.FILE_LIST = parse_files(cfg.FILE_LIST, max(1, int(num_seq)))
48
-
49
- # Audio speed
50
- cfg.AUDIO_SPEED = max(0.1, 1.0 / (audio_speed * -1)) if audio_speed < 0 else max(1.0, float(audio_speed))
51
-
52
- # Add config items to each file list entry.
53
- # We have to do this for Windows which does not
54
- # support fork() and thus each process has to
55
- # have its own config. USE LINUX!
56
- # flist = [(entry, max(cfg.SIG_LENGTH, float(seq_length)), cfg.getConfig()) for entry in cfg.FILE_LIST]
57
- flist = [(entry, float(seq_length), cfg.get_config()) for entry in cfg.FILE_LIST]
58
-
59
- result_list = []
60
-
61
- # Extract segments
62
- if cfg.CPU_THREADS < 2:
63
- for i, entry in enumerate(flist):
64
- result = extract_segments_wrapper(entry)
65
- result_list.append(result)
66
-
67
- if progress is not None:
68
- progress((i, len(flist)), total=len(flist), unit="files")
69
- else:
70
- with concurrent.futures.ProcessPoolExecutor(max_workers=cfg.CPU_THREADS) as executor:
71
- futures = (executor.submit(extract_segments_wrapper, arg) for arg in flist)
72
- for i, f in enumerate(concurrent.futures.as_completed(futures), start=1):
73
- if progress is not None:
74
- progress((i, len(flist)), total=len(flist), unit="files")
75
- result = f.result()
76
-
77
- result_list.append(result)
78
-
79
- return [[os.path.relpath(r[0], audio_dir), r[1]] for r in result_list]
80
-
81
-
82
- def build_segments_tab():
83
- with gr.Tab(loc.localize("segments-tab-title")):
84
- audio_directory_state = gr.State()
85
- result_directory_state = gr.State()
86
- output_directory_state = gr.State()
87
-
88
- def select_directory_to_state_and_tb(state_key):
89
- return (gu.select_directory(collect_files=False, state_key=state_key),) * 2
90
-
91
- with gr.Row():
92
- select_audio_directory_btn = gr.Button(
93
- loc.localize("segments-tab-select-audio-input-directory-button-label")
94
- )
95
- selected_audio_directory_tb = gr.Textbox(show_label=False, interactive=False)
96
- select_audio_directory_btn.click(
97
- partial(select_directory_to_state_and_tb, state_key="segments-audio-dir"),
98
- outputs=[selected_audio_directory_tb, audio_directory_state],
99
- show_progress=False,
100
- )
101
-
102
- with gr.Row():
103
- select_result_directory_btn = gr.Button(
104
- loc.localize("segments-tab-select-results-input-directory-button-label")
105
- )
106
- selected_result_directory_tb = gr.Textbox(
107
- show_label=False,
108
- interactive=False,
109
- placeholder=loc.localize("segments-tab-results-input-textbox-placeholder"),
110
- )
111
- select_result_directory_btn.click(
112
- partial(select_directory_to_state_and_tb, state_key="segments-result-dir"),
113
- outputs=[result_directory_state, selected_result_directory_tb],
114
- show_progress=False,
115
- )
116
-
117
- with gr.Row():
118
- select_output_directory_btn = gr.Button(loc.localize("segments-tab-output-selection-button-label"))
119
- selected_output_directory_tb = gr.Textbox(
120
- show_label=False,
121
- interactive=False,
122
- placeholder=loc.localize("segments-tab-output-selection-textbox-placeholder"),
123
- )
124
- select_output_directory_btn.click(
125
- partial(select_directory_to_state_and_tb, state_key="segments-output-dir"),
126
- outputs=[selected_output_directory_tb, output_directory_state],
127
- show_progress=False,
128
- )
129
-
130
- min_conf_slider = gr.Slider(
131
- minimum=0.1,
132
- maximum=0.99,
133
- step=0.01,
134
- value=cfg.MIN_CONFIDENCE,
135
- label=loc.localize("segments-tab-min-confidence-slider-label"),
136
- info=loc.localize("segments-tab-min-confidence-slider-info"),
137
- )
138
- num_seq_number = gr.Number(
139
- 100,
140
- label=loc.localize("segments-tab-max-seq-number-label"),
141
- info=loc.localize("segments-tab-max-seq-number-info"),
142
- minimum=1,
143
- )
144
- audio_speed_slider = gr.Slider(
145
- minimum=-10,
146
- maximum=10,
147
- value=cfg.AUDIO_SPEED,
148
- step=1,
149
- label=loc.localize("inference-settings-audio-speed-slider-label"),
150
- info=loc.localize("inference-settings-audio-speed-slider-info"),
151
- )
152
- seq_length_number = gr.Number(
153
- cfg.SIG_LENGTH,
154
- label=loc.localize("segments-tab-seq-length-number-label"),
155
- info=loc.localize("segments-tab-seq-length-number-info"),
156
- minimum=0.1,
157
- )
158
- threads_number = gr.Number(
159
- 4,
160
- label=loc.localize("segments-tab-threads-number-label"),
161
- info=loc.localize("segments-tab-threads-number-info"),
162
- minimum=1,
163
- )
164
-
165
- extract_segments_btn = gr.Button(loc.localize("segments-tab-extract-button-label"), variant="huggingface")
166
-
167
- result_grid = gr.Matrix(
168
- headers=[
169
- loc.localize("segments-tab-result-dataframe-column-file-header"),
170
- loc.localize("segments-tab-result-dataframe-column-execution-header"),
171
- ],
172
- )
173
-
174
- extract_segments_btn.click(
175
- _extract_segments,
176
- inputs=[
177
- audio_directory_state,
178
- result_directory_state,
179
- output_directory_state,
180
- min_conf_slider,
181
- num_seq_number,
182
- audio_speed_slider,
183
- seq_length_number,
184
- threads_number,
185
- ],
186
- outputs=result_grid,
187
- )
188
-
189
-
190
- if __name__ == "__main__":
191
- gu.open_window(build_segments_tab)
1
+ import concurrent.futures
2
+ import os
3
+ from functools import partial
4
+
5
+ import gradio as gr
6
+
7
+ import birdnet_analyzer.config as cfg
8
+ import birdnet_analyzer.gui.localization as loc
9
+ import birdnet_analyzer.gui.utils as gu
10
+ from birdnet_analyzer.segments.utils import extract_segments
11
+
12
+
13
+ def extract_segments_wrapper(entry):
14
+ return (entry[0][0], extract_segments(entry))
15
+
16
+
17
+ @gu.gui_runtime_error_handler
18
+ def _extract_segments(
19
+ audio_dir, result_dir, output_dir, min_conf, num_seq, audio_speed, seq_length, threads, progress=gr.Progress()
20
+ ):
21
+ from birdnet_analyzer.segments.utils import parse_files, parse_folders
22
+
23
+ gu.validate(audio_dir, loc.localize("validation-no-audio-directory-selected"))
24
+
25
+ if not result_dir:
26
+ result_dir = audio_dir
27
+
28
+ if not output_dir:
29
+ output_dir = audio_dir
30
+
31
+ if progress is not None:
32
+ progress(0, desc=f"{loc.localize('progress-search')} ...")
33
+
34
+ # Parse audio and result folders
35
+ cfg.FILE_LIST = parse_folders(audio_dir, result_dir)
36
+
37
+ # Set output folder
38
+ cfg.OUTPUT_PATH = output_dir
39
+
40
+ # Set number of threads
41
+ cfg.CPU_THREADS = int(threads)
42
+
43
+ # Set confidence threshold
44
+ cfg.MIN_CONFIDENCE = max(0.01, min(0.99, min_conf))
45
+
46
+ # Parse file list and make list of segments
47
+ cfg.FILE_LIST = parse_files(cfg.FILE_LIST, max(1, int(num_seq)))
48
+
49
+ # Audio speed
50
+ cfg.AUDIO_SPEED = max(0.1, 1.0 / (audio_speed * -1)) if audio_speed < 0 else max(1.0, float(audio_speed))
51
+
52
+ # Add config items to each file list entry.
53
+ # We have to do this for Windows which does not
54
+ # support fork() and thus each process has to
55
+ # have its own config. USE LINUX!
56
+ # flist = [(entry, max(cfg.SIG_LENGTH, float(seq_length)), cfg.getConfig()) for entry in cfg.FILE_LIST]
57
+ flist = [(entry, float(seq_length), cfg.get_config()) for entry in cfg.FILE_LIST]
58
+
59
+ result_list = []
60
+
61
+ # Extract segments
62
+ if cfg.CPU_THREADS < 2:
63
+ for i, entry in enumerate(flist):
64
+ result = extract_segments_wrapper(entry)
65
+ result_list.append(result)
66
+
67
+ if progress is not None:
68
+ progress((i, len(flist)), total=len(flist), unit="files")
69
+ else:
70
+ with concurrent.futures.ProcessPoolExecutor(max_workers=cfg.CPU_THREADS) as executor:
71
+ futures = (executor.submit(extract_segments_wrapper, arg) for arg in flist)
72
+ for i, f in enumerate(concurrent.futures.as_completed(futures), start=1):
73
+ if progress is not None:
74
+ progress((i, len(flist)), total=len(flist), unit="files")
75
+ result = f.result()
76
+
77
+ result_list.append(result)
78
+
79
+ return [[os.path.relpath(r[0], audio_dir), r[1]] for r in result_list]
80
+
81
+
82
+ def build_segments_tab():
83
+ with gr.Tab(loc.localize("segments-tab-title")):
84
+ audio_directory_state = gr.State()
85
+ result_directory_state = gr.State()
86
+ output_directory_state = gr.State()
87
+
88
+ def select_directory_to_state_and_tb(state_key):
89
+ return (gu.select_directory(collect_files=False, state_key=state_key),) * 2
90
+
91
+ with gr.Row():
92
+ select_audio_directory_btn = gr.Button(
93
+ loc.localize("segments-tab-select-audio-input-directory-button-label")
94
+ )
95
+ selected_audio_directory_tb = gr.Textbox(show_label=False, interactive=False)
96
+ select_audio_directory_btn.click(
97
+ partial(select_directory_to_state_and_tb, state_key="segments-audio-dir"),
98
+ outputs=[selected_audio_directory_tb, audio_directory_state],
99
+ show_progress=False,
100
+ )
101
+
102
+ with gr.Row():
103
+ select_result_directory_btn = gr.Button(
104
+ loc.localize("segments-tab-select-results-input-directory-button-label")
105
+ )
106
+ selected_result_directory_tb = gr.Textbox(
107
+ show_label=False,
108
+ interactive=False,
109
+ placeholder=loc.localize("segments-tab-results-input-textbox-placeholder"),
110
+ )
111
+ select_result_directory_btn.click(
112
+ partial(select_directory_to_state_and_tb, state_key="segments-result-dir"),
113
+ outputs=[result_directory_state, selected_result_directory_tb],
114
+ show_progress=False,
115
+ )
116
+
117
+ with gr.Row():
118
+ select_output_directory_btn = gr.Button(loc.localize("segments-tab-output-selection-button-label"))
119
+ selected_output_directory_tb = gr.Textbox(
120
+ show_label=False,
121
+ interactive=False,
122
+ placeholder=loc.localize("segments-tab-output-selection-textbox-placeholder"),
123
+ )
124
+ select_output_directory_btn.click(
125
+ partial(select_directory_to_state_and_tb, state_key="segments-output-dir"),
126
+ outputs=[selected_output_directory_tb, output_directory_state],
127
+ show_progress=False,
128
+ )
129
+
130
+ min_conf_slider = gr.Slider(
131
+ minimum=0.1,
132
+ maximum=0.99,
133
+ step=0.01,
134
+ value=cfg.MIN_CONFIDENCE,
135
+ label=loc.localize("segments-tab-min-confidence-slider-label"),
136
+ info=loc.localize("segments-tab-min-confidence-slider-info"),
137
+ )
138
+ num_seq_number = gr.Number(
139
+ 100,
140
+ label=loc.localize("segments-tab-max-seq-number-label"),
141
+ info=loc.localize("segments-tab-max-seq-number-info"),
142
+ minimum=1,
143
+ )
144
+ audio_speed_slider = gr.Slider(
145
+ minimum=-10,
146
+ maximum=10,
147
+ value=cfg.AUDIO_SPEED,
148
+ step=1,
149
+ label=loc.localize("inference-settings-audio-speed-slider-label"),
150
+ info=loc.localize("inference-settings-audio-speed-slider-info"),
151
+ )
152
+ seq_length_number = gr.Number(
153
+ cfg.SIG_LENGTH,
154
+ label=loc.localize("segments-tab-seq-length-number-label"),
155
+ info=loc.localize("segments-tab-seq-length-number-info"),
156
+ minimum=0.1,
157
+ )
158
+ threads_number = gr.Number(
159
+ 4,
160
+ label=loc.localize("segments-tab-threads-number-label"),
161
+ info=loc.localize("segments-tab-threads-number-info"),
162
+ minimum=1,
163
+ )
164
+
165
+ extract_segments_btn = gr.Button(loc.localize("segments-tab-extract-button-label"), variant="huggingface")
166
+
167
+ result_grid = gr.Matrix(
168
+ headers=[
169
+ loc.localize("segments-tab-result-dataframe-column-file-header"),
170
+ loc.localize("segments-tab-result-dataframe-column-execution-header"),
171
+ ],
172
+ )
173
+
174
+ extract_segments_btn.click(
175
+ _extract_segments,
176
+ inputs=[
177
+ audio_directory_state,
178
+ result_directory_state,
179
+ output_directory_state,
180
+ min_conf_slider,
181
+ num_seq_number,
182
+ audio_speed_slider,
183
+ seq_length_number,
184
+ threads_number,
185
+ ],
186
+ outputs=result_grid,
187
+ )
188
+
189
+
190
+ if __name__ == "__main__":
191
+ gu.open_window(build_segments_tab)
@@ -1,129 +1,128 @@
1
- import os
2
- from pathlib import Path
3
- import json
4
-
5
- import birdnet_analyzer.gui.utils as gu
6
- import birdnet_analyzer.utils as utils
7
-
8
-
9
- FALLBACK_LANGUAGE = "en"
10
- SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
11
- GUI_SETTINGS_PATH = os.path.join(gu.APPDIR if utils.FROZEN else os.path.dirname(SCRIPT_DIR), "gui-settings.json")
12
- LANG_DIR = str(Path(SCRIPT_DIR).parent / "lang")
13
- STATE_SETTINGS_PATH = os.path.join(gu.APPDIR if utils.FROZEN else os.path.dirname(SCRIPT_DIR), "state.json")
14
-
15
-
16
- def get_state_dict() -> dict:
17
- """
18
- Retrieves the state dictionary from a JSON file specified by STATE_SETTINGS_PATH.
19
-
20
- If the file does not exist, it creates an empty JSON file and returns an empty dictionary.
21
- If any other exception occurs during file operations, it logs the error and returns an empty dictionary.
22
-
23
- Returns:
24
- dict: The state dictionary loaded from the JSON file, or an empty dictionary if the file does not exist or an error occurs.
25
- """
26
- try:
27
- with open(STATE_SETTINGS_PATH, "r", encoding="utf-8") as f:
28
- return json.load(f)
29
- except FileNotFoundError:
30
- try:
31
- with open(STATE_SETTINGS_PATH, "w", encoding="utf-8") as f:
32
- json.dump({}, f)
33
- return {}
34
- except Exception as e:
35
- utils.write_error_log(e)
36
- return {}
37
-
38
-
39
- def get_state(key: str, default=None) -> str:
40
- """
41
- Retrieves the value associated with the given key from the state dictionary.
42
-
43
- Args:
44
- key (str): The key to look up in the state dictionary.
45
- default: The value to return if the key is not found. Defaults to None.
46
-
47
- Returns:
48
- str: The value associated with the key if found, otherwise the default value.
49
- """
50
- return get_state_dict().get(key, default)
51
-
52
-
53
- def set_state(key: str, value: str):
54
- """
55
- Updates the state dictionary with the given key-value pair and writes it to a JSON file.
56
-
57
- Args:
58
- key (str): The key to update in the state dictionary.
59
- value (str): The value to associate with the key in the state dictionary.
60
- """
61
- try:
62
- state = get_state_dict()
63
- state[key] = value
64
-
65
- with open(STATE_SETTINGS_PATH, "w") as f:
66
- json.dump(state, f, indent=4)
67
- except Exception as e:
68
- utils.write_error_log(e)
69
-
70
-
71
- def ensure_settings_file():
72
- """
73
- Ensures that the settings file exists at the specified path. If the file does not exist,
74
- it creates a new settings file with default settings.
75
-
76
- If the file creation fails, the error is logged.
77
- """
78
- if not os.path.exists(GUI_SETTINGS_PATH):
79
- try:
80
- with open(GUI_SETTINGS_PATH, "w") as f:
81
- settings = {"language-id": FALLBACK_LANGUAGE, "theme": "light"}
82
- f.write(json.dumps(settings, indent=4))
83
- except Exception as e:
84
- utils.write_error_log(e)
85
-
86
-
87
- def get_setting(key, default=None):
88
- """
89
- Retrieves the value associated with the given key from the settings file.
90
-
91
- Args:
92
- key (str): The key to look up in the settings file.
93
- default: The value to return if the key is not found. Defaults to None.
94
-
95
- Returns:
96
- str: The value associated with the key if found, otherwise the default value.
97
- """
98
- ensure_settings_file()
99
-
100
- try:
101
- with open(GUI_SETTINGS_PATH, "r", encoding="utf-8") as f:
102
- settings_dict: dict = json.load(f)
103
-
104
- return settings_dict.get(key, default)
105
- except FileNotFoundError:
106
- return default
107
-
108
-
109
- def set_setting(key, value):
110
- ensure_settings_file()
111
- settings_dict = {}
112
-
113
- try:
114
- with open(GUI_SETTINGS_PATH, "r+", encoding="utf-8") as f:
115
- settings_dict = json.load(f)
116
- settings_dict[key] = value
117
- f.seek(0)
118
- json.dump(settings_dict, f, indent=4)
119
- f.truncate()
120
-
121
- except FileNotFoundError:
122
- pass
123
-
124
-
125
- def theme():
126
- options = ("light", "dark")
127
- current_time = get_setting("theme", "light")
128
-
129
- return current_time if current_time in options else "light"
1
+ import json
2
+ import os
3
+ from pathlib import Path
4
+
5
+ import birdnet_analyzer.gui.utils as gu
6
+ from birdnet_analyzer import utils
7
+
8
+ FALLBACK_LANGUAGE = "en"
9
+ SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
10
+ GUI_SETTINGS_PATH = os.path.join(gu.APPDIR if utils.FROZEN else os.path.dirname(SCRIPT_DIR), "gui-settings.json")
11
+ LANG_DIR = str(Path(SCRIPT_DIR).parent / "lang")
12
+ STATE_SETTINGS_PATH = os.path.join(gu.APPDIR if utils.FROZEN else os.path.dirname(SCRIPT_DIR), "state.json")
13
+
14
+
15
+ def get_state_dict() -> dict:
16
+ """
17
+ Retrieves the state dictionary from a JSON file specified by STATE_SETTINGS_PATH.
18
+
19
+ If the file does not exist, it creates an empty JSON file and returns an empty dictionary.
20
+ If any other exception occurs during file operations, it logs the error and returns an empty dictionary.
21
+
22
+ Returns:
23
+ dict: The state dictionary loaded from the JSON file, or an empty dictionary if the file does not exist or an error occurs.
24
+ """
25
+ try:
26
+ with open(STATE_SETTINGS_PATH, encoding="utf-8") as f:
27
+ return json.load(f)
28
+ except FileNotFoundError:
29
+ try:
30
+ with open(STATE_SETTINGS_PATH, "w", encoding="utf-8") as f:
31
+ json.dump({}, f)
32
+ return {}
33
+ except Exception as e:
34
+ utils.write_error_log(e)
35
+ return {}
36
+
37
+
38
+ def get_state(key: str, default=None) -> str:
39
+ """
40
+ Retrieves the value associated with the given key from the state dictionary.
41
+
42
+ Args:
43
+ key (str): The key to look up in the state dictionary.
44
+ default: The value to return if the key is not found. Defaults to None.
45
+
46
+ Returns:
47
+ str: The value associated with the key if found, otherwise the default value.
48
+ """
49
+ return get_state_dict().get(key, default)
50
+
51
+
52
+ def set_state(key: str, value: str):
53
+ """
54
+ Updates the state dictionary with the given key-value pair and writes it to a JSON file.
55
+
56
+ Args:
57
+ key (str): The key to update in the state dictionary.
58
+ value (str): The value to associate with the key in the state dictionary.
59
+ """
60
+ try:
61
+ state = get_state_dict()
62
+ state[key] = value
63
+
64
+ with open(STATE_SETTINGS_PATH, "w") as f:
65
+ json.dump(state, f, indent=4)
66
+ except Exception as e:
67
+ utils.write_error_log(e)
68
+
69
+
70
+ def ensure_settings_file():
71
+ """
72
+ Ensures that the settings file exists at the specified path. If the file does not exist,
73
+ it creates a new settings file with default settings.
74
+
75
+ If the file creation fails, the error is logged.
76
+ """
77
+ if not os.path.exists(GUI_SETTINGS_PATH):
78
+ try:
79
+ with open(GUI_SETTINGS_PATH, "w") as f:
80
+ settings = {"language-id": FALLBACK_LANGUAGE, "theme": "light"}
81
+ f.write(json.dumps(settings, indent=4))
82
+ except Exception as e:
83
+ utils.write_error_log(e)
84
+
85
+
86
+ def get_setting(key, default=None):
87
+ """
88
+ Retrieves the value associated with the given key from the settings file.
89
+
90
+ Args:
91
+ key (str): The key to look up in the settings file.
92
+ default: The value to return if the key is not found. Defaults to None.
93
+
94
+ Returns:
95
+ str: The value associated with the key if found, otherwise the default value.
96
+ """
97
+ ensure_settings_file()
98
+
99
+ try:
100
+ with open(GUI_SETTINGS_PATH, encoding="utf-8") as f:
101
+ settings_dict: dict = json.load(f)
102
+
103
+ return settings_dict.get(key, default)
104
+ except FileNotFoundError:
105
+ return default
106
+
107
+
108
+ def set_setting(key, value):
109
+ ensure_settings_file()
110
+ settings_dict = {}
111
+
112
+ try:
113
+ with open(GUI_SETTINGS_PATH, "r+", encoding="utf-8") as f:
114
+ settings_dict = json.load(f)
115
+ settings_dict[key] = value
116
+ f.seek(0)
117
+ json.dump(settings_dict, f, indent=4)
118
+ f.truncate()
119
+
120
+ except FileNotFoundError:
121
+ pass
122
+
123
+
124
+ def theme():
125
+ options = ("light", "dark")
126
+ current_time = get_setting("theme", "light")
127
+
128
+ return current_time if current_time in options else "light"