avans06 commited on
Commit
a3c1adc
·
1 Parent(s): fbef048

Refactor: Consolidate Gradio UI and unify submit logic

Browse files
Files changed (5) hide show
  1. .gitignore +206 -0
  2. README.md +1 -2
  3. app.py +107 -126
  4. requirements.txt +1 -0
  5. webui.bat +162 -0
.gitignore ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.pt
2
+ *.ckpt
3
+ *.onnx
4
+ t5_g2p_model/
5
+ embeddings/
6
+ checkpoints/
7
+
8
+ val_images/
9
+ val_audios/
10
+ lightning_logs/
11
+ lightning_logs_/
12
+ train_images/
13
+ train_audios/
14
+ # Byte-compiled / optimized / DLL files
15
+ __pycache__/
16
+ *.py[cod]
17
+ *$py.class
18
+
19
+ # C extensions
20
+ *.so
21
+
22
+ # Distribution / packaging
23
+ .idea/
24
+ .Python
25
+ build/
26
+ develop-eggs/
27
+ dist/
28
+ downloads/
29
+ eggs/
30
+ .eggs/
31
+ lib/
32
+ lib64/
33
+ parts/
34
+ sdist/
35
+ var/
36
+ wheels/
37
+ share/python-wheels/
38
+ *.egg-info/
39
+ .installed.cfg
40
+ *.egg
41
+ MANIFEST
42
+
43
+ # PyInstaller
44
+ # Usually these files are written by a python script from a template
45
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
46
+ *.manifest
47
+ *.spec
48
+
49
+ # Installer logs
50
+ pip-log.txt
51
+ pip-delete-this-directory.txt
52
+
53
+ # Unit test / coverage reports
54
+ htmlcov/
55
+ .tox/
56
+ .nox/
57
+ .coverage
58
+ .coverage.*
59
+ .cache
60
+ nosetests.xml
61
+ coverage.xml
62
+ *.cover
63
+ *.py,cover
64
+ .hypothesis/
65
+ .pytest_cache/
66
+ cover/
67
+
68
+ # Translations
69
+ *.mo
70
+ *.pot
71
+
72
+ # Django stuff:
73
+ *.log
74
+ local_settings.py
75
+ db.sqlite3
76
+ db.sqlite3-journal
77
+
78
+ # Flask stuff:
79
+ instance/
80
+ .webassets-cache
81
+
82
+ # Scrapy stuff:
83
+ .scrapy
84
+
85
+ # Sphinx documentation
86
+ docs/_build/
87
+
88
+ # PyBuilder
89
+ .pybuilder/
90
+ target/
91
+
92
+ # Jupyter Notebook
93
+ .ipynb_checkpoints
94
+
95
+ # IPython
96
+ profile_default/
97
+ ipython_config.py
98
+
99
+ # pyenv
100
+ # For a library or package, you might want to ignore these files since the code is
101
+ # intended to run in multiple environments; otherwise, check them in:
102
+ # .python-version
103
+
104
+ # pipenv
105
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
106
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
107
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
108
+ # install all needed dependencies.
109
+ #Pipfile.lock
110
+
111
+ # poetry
112
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
113
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
114
+ # commonly ignored for libraries.
115
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
116
+ #poetry.lock
117
+
118
+ # pdm
119
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
120
+ #pdm.lock
121
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
122
+ # in version control.
123
+ # https://pdm.fming.dev/#use-with-ide
124
+ .pdm.toml
125
+
126
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
127
+ __pypackages__/
128
+
129
+ # Celery stuff
130
+ celerybeat-schedule
131
+ celerybeat.pid
132
+
133
+ # SageMath parsed files
134
+ *.sage.py
135
+
136
+ # Environments
137
+ .env
138
+ .venv
139
+ env/
140
+ venv/
141
+ ENV/
142
+ env.bak/
143
+ venv.bak/
144
+
145
+ # Spyder project settings
146
+ .spyderproject
147
+ .spyproject
148
+
149
+ # Rope project settings
150
+ .ropeproject
151
+
152
+ # mkdocs documentation
153
+ /site
154
+
155
+ # mypy
156
+ .mypy_cache/
157
+ .dmypy.json
158
+ dmypy.json
159
+
160
+ # Pyre type checker
161
+ .pyre/
162
+
163
+ # pytype static type analyzer
164
+ .pytype/
165
+
166
+ # Cython debug symbols
167
+ cython_debug/
168
+
169
+ # PyCharm
170
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
171
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
172
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
173
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
174
+ #.idea/
175
+ *.txt
176
+ !requirements.txt
177
+ *.log
178
+ *.flac
179
+ minio_config.yaml
180
+ .history/*
181
+ __pycache__/*
182
+ train.log
183
+ *.mp3
184
+ *.tar.gz
185
+ __pycache__/
186
+ demo_examples/
187
+ nohup.out
188
+ test_results/*
189
+ nohup.out
190
+ text_audio_align/*
191
+ remote/*
192
+ MG2P/*
193
+ audio_getter.py
194
+ refiner_loss_debug/
195
+ outputs/*
196
+ !outputs/
197
+ save_checkpoint.ipynb
198
+ repos/*
199
+ app_demo.py
200
+ ui/components_demo.py
201
+ data_sampler_demo.py
202
+ pipeline_ace_step_demo.py
203
+
204
+ .vs
205
+ .gradio
206
+ venv
README.md CHANGED
@@ -4,8 +4,7 @@ emoji: 📈
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
- sdk_version: 4.44.1
8
- python_version: 3.8.9
9
  app_file: app.py
10
  pinned: false
11
  license: apache-2.0
 
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 5.29.1
 
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
app.py CHANGED
@@ -39,7 +39,7 @@ def convert_to_wav(in_filename: str) -> str:
39
  logging.info(f"Converting '{in_filename}' to '{out_filename}'")
40
 
41
  _ = os.system(
42
- f"ffmpeg -hide_banner -i '{in_filename}' -ar 16000 -ac 1 '{out_filename}' -y"
43
  )
44
 
45
  return out_filename
@@ -55,67 +55,82 @@ def build_html_output(s: str, style: str = "result_item_success"):
55
  """
56
 
57
 
58
- def process_url(
59
  repo_id: str,
60
- url: str,
 
 
61
  ):
62
- logging.info(f"Processing URL: {url}")
63
- with tempfile.NamedTemporaryFile() as f:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  try:
65
- urllib.request.urlretrieve(url, f.name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
 
 
 
67
  return process(
68
- in_filename=f.name,
69
  repo_id=repo_id,
70
  )
71
  except Exception as e:
72
- logging.info(str(e))
73
- return "", build_html_output(str(e), "result_item_error")
74
-
75
-
76
- def process_uploaded_file(
77
- repo_id: str,
78
- in_filename: str,
79
- ):
80
- if in_filename is None or in_filename == "":
81
- return "", build_html_output(
82
- "Please first upload a file and then click "
83
- 'the button "submit for recognition"',
84
- "result_item_error",
85
- )
86
-
87
- logging.info(f"Processing uploaded file: {in_filename}")
88
- try:
89
- return process(
90
- in_filename=in_filename,
91
- repo_id=repo_id,
92
- )
93
- except Exception as e:
94
- logging.info(str(e))
95
- return "", build_html_output(str(e), "result_item_error")
96
-
97
-
98
- def process_microphone(
99
- repo_id: str,
100
- in_filename: str,
101
- ):
102
- if in_filename is None or in_filename == "":
103
- return "", build_html_output(
104
- "Please first click 'Record from microphone', speak, "
105
- "click 'Stop recording', and then "
106
- "click the button 'submit for recognition'",
107
- "result_item_error",
108
- )
109
 
110
- logging.info(f"Processing microphone: {in_filename}")
111
- try:
112
- return process(
113
- in_filename=in_filename,
114
- repo_id=repo_id,
115
- )
116
- except Exception as e:
117
- logging.info(str(e))
118
- return "", build_html_output(str(e), "result_item_error")
119
 
120
 
121
  def process(
@@ -136,9 +151,10 @@ def process(
136
  tagger = get_pretrained_model(repo_id)
137
 
138
  events = decode(tagger, filename)
139
-
 
140
  events = [[e.name, f"{e.prob:.2f}"] for e in events]
141
-
142
  date_time = now.strftime("%Y-%m-%d %H:%M:%S.%f")
143
  end = time.time()
144
 
@@ -164,7 +180,7 @@ def process(
164
  logging.info(info)
165
  logging.info(f"\nrepo_id: {repo_id}\nDetected events: {events}")
166
 
167
- return events, build_html_output(info)
168
 
169
 
170
  title = "# Audio tagging with [Next-gen Kaldi](https://github.com/k2-fsa) "
@@ -211,23 +227,6 @@ with demo:
211
  type="filepath",
212
  label="Upload from disk",
213
  )
214
- upload_button = gr.Button("Submit for recognition")
215
-
216
- upload_output = gr.Dataframe(headers=["Event", "Probability"])
217
- uploaded_html_info = gr.HTML(label="Info")
218
-
219
- gr.Examples(
220
- examples=examples,
221
- inputs=[
222
- model_dropdown,
223
- uploaded_file,
224
- ],
225
- outputs=[
226
- upload_output,
227
- uploaded_html_info,
228
- ],
229
- fn=process_uploaded_file,
230
- )
231
 
232
  with gr.TabItem("Record from microphone"):
233
  microphone = gr.Audio(
@@ -236,23 +235,6 @@ with demo:
236
  label="Record from microphone",
237
  )
238
 
239
- record_button = gr.Button("Submit for recognition")
240
- microphone_output = gr.Dataframe(headers=["Event", "Probability"])
241
- recorded_html_info = gr.HTML(label="Info")
242
-
243
- gr.Examples(
244
- examples=examples,
245
- inputs=[
246
- model_dropdown,
247
- microphone,
248
- ],
249
- outputs=[
250
- microphone_output,
251
- recorded_html_info,
252
- ],
253
- fn=process_microphone,
254
- )
255
-
256
  with gr.TabItem("From URL"):
257
  url_textbox = gr.Textbox(
258
  max_lines=1,
@@ -261,42 +243,41 @@ with demo:
261
  interactive=True,
262
  )
263
 
264
- url_button = gr.Button("Submit for recognition")
265
- url_output = gr.Dataframe(headers=["Event", "Probability"])
266
- url_html_info = gr.HTML(label="Info")
267
-
268
- upload_button.click(
269
- process_uploaded_file,
270
- inputs=[
271
- model_dropdown,
272
- uploaded_file,
273
- ],
274
- outputs=[
275
- upload_output,
276
- uploaded_html_info,
277
- ],
278
- )
279
-
280
- record_button.click(
281
- process_microphone,
282
- inputs=[
283
- model_dropdown,
284
- microphone,
285
- ],
286
- outputs=[
287
- microphone_output,
288
- recorded_html_info,
289
- ],
290
- )
291
 
292
- url_button.click(
293
- process_url,
294
- inputs=[
295
- model_dropdown,
296
- url_textbox,
297
- ],
298
- outputs=[url_output, url_html_info],
299
- )
 
 
 
 
 
 
 
300
 
301
  gr.Markdown(description)
302
 
@@ -305,4 +286,4 @@ if __name__ == "__main__":
305
 
306
  logging.basicConfig(format=formatter, level=logging.INFO)
307
 
308
- demo.launch()
 
39
  logging.info(f"Converting '{in_filename}' to '{out_filename}'")
40
 
41
  _ = os.system(
42
+ f"ffmpeg -hide_banner -i \"{in_filename}\" -ar 16000 -ac 1 \"{out_filename}\" -y"
43
  )
44
 
45
  return out_filename
 
55
  """
56
 
57
 
58
+ def submit_fn(
59
  repo_id: str,
60
+ uploaded_file_path: str,
61
+ microphone_audio_path: str,
62
+ url_text: str,
63
  ):
64
+ in_filename = None
65
+ source_description = ""
66
+
67
+ if uploaded_file_path:
68
+ in_filename = uploaded_file_path
69
+ source_description = "uploaded file"
70
+ logging.info(f"Processing {source_description}: {in_filename}")
71
+ if not os.path.exists(in_filename):
72
+ return "", [], build_html_output(
73
+ f"Uploaded file not found: {in_filename}, "
74
+ "Please first upload a file and then click "
75
+ 'the button "submit for recognition"',
76
+ "result_item_error",
77
+ )
78
+
79
+ elif microphone_audio_path:
80
+ in_filename = microphone_audio_path
81
+ source_description = "microphone recording"
82
+ logging.info(f"Processing {source_description}: {in_filename}")
83
+ if not os.path.exists(in_filename):
84
+ return "", [], build_html_output(
85
+ f"Microphone recording not found: {in_filename}, "
86
+ "Please first click 'Record from microphone', speak, "
87
+ "click 'Stop recording', and then "
88
+ "click the button 'submit for recognition'",
89
+ "result_item_error"
90
+ )
91
+
92
+ elif url_text and url_text.strip():
93
+ source_description = "URL"
94
+ logging.info(f"Processing {source_description}: {url_text}")
95
+ # Ensure a temporary file is created that persists until process() is done with it.
96
+ # Using delete=False and manual cleanup is safer here.
97
+ temp_file = None
98
  try:
99
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".tmpaudio") as f:
100
+ temp_file = f.name # Store the name for cleanup
101
+ urllib.request.urlretrieve(url_text, temp_file)
102
+ in_filename = temp_file
103
+ # Process the downloaded file
104
+ eventStr, events, html_info = process(repo_id=repo_id, in_filename=in_filename)
105
+ # Clean up the temporary file after processing
106
+ if temp_file and os.path.exists(temp_file):
107
+ os.unlink(temp_file)
108
+ return eventStr, events, html_info
109
+ except Exception as e:
110
+ logging.error(f"Error processing URL {url_text}: {e}", exc_info=True)
111
+ # Clean up the temporary file in case of error
112
+ if temp_file and os.path.exists(temp_file):
113
+ os.unlink(temp_file)
114
+ return "", [], build_html_output(f"Error processing URL: {str(e)}", "result_item_error")
115
+ else:
116
+ return "", [], build_html_output(
117
+ "Please provide an audio input via upload, microphone, or URL.",
118
+ "result_item_error",
119
+ )
120
 
121
+ # Common processing for file-based inputs (upload, mic)
122
+ if in_filename:
123
+ try:
124
  return process(
125
+ in_filename=in_filename,
126
  repo_id=repo_id,
127
  )
128
  except Exception as e:
129
+ logging.error(f"Error processing {source_description} {in_filename}: {e}", exc_info=True)
130
+ return "", [], build_html_output(f"Error processing {source_description}: {str(e)}", "result_item_error")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
+ # Should not be reached if logic is correct, but as a fallback:
133
+ return "", [], build_html_output("No valid input provided.", "result_item_error")
 
 
 
 
 
 
 
134
 
135
 
136
  def process(
 
151
  tagger = get_pretrained_model(repo_id)
152
 
153
  events = decode(tagger, filename)
154
+
155
+ eventStr = ", ".join([e.name for e in events])
156
  events = [[e.name, f"{e.prob:.2f}"] for e in events]
157
+
158
  date_time = now.strftime("%Y-%m-%d %H:%M:%S.%f")
159
  end = time.time()
160
 
 
180
  logging.info(info)
181
  logging.info(f"\nrepo_id: {repo_id}\nDetected events: {events}")
182
 
183
+ return eventStr, events, build_html_output(info)
184
 
185
 
186
  title = "# Audio tagging with [Next-gen Kaldi](https://github.com/k2-fsa) "
 
227
  type="filepath",
228
  label="Upload from disk",
229
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
  with gr.TabItem("Record from microphone"):
232
  microphone = gr.Audio(
 
235
  label="Record from microphone",
236
  )
237
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  with gr.TabItem("From URL"):
239
  url_textbox = gr.Textbox(
240
  max_lines=1,
 
243
  interactive=True,
244
  )
245
 
246
+ submit_button = gr.Button("Submit for recognition", variant="primary")
247
+
248
+ output_string = gr.Textbox(label="Event (string)", show_label=True, show_copy_button=True)
249
+ output_dataframe = gr.Dataframe(headers=["Event", "Probability"], label="Detected Events")
250
+ output_html_info = gr.HTML(label="Processing Info")
251
+
252
+ gr.Examples(
253
+ examples=examples,
254
+ inputs=[
255
+ model_dropdown,
256
+ uploaded_file,
257
+ ],
258
+ outputs=[
259
+ output_string,
260
+ output_dataframe,
261
+ output_html_info,
262
+ ],
263
+ fn=submit_fn,
264
+ )
 
 
 
 
 
 
 
 
265
 
266
+ # Connect the submit button to the unified function
267
+ submit_button.click(
268
+ fn=submit_fn,
269
+ inputs=[
270
+ model_dropdown,
271
+ uploaded_file,
272
+ microphone,
273
+ url_textbox,
274
+ ],
275
+ outputs=[
276
+ output_string,
277
+ output_dataframe,
278
+ output_html_info,
279
+ ],
280
+ )
281
 
282
  gr.Markdown(description)
283
 
 
286
 
287
  logging.basicConfig(format=formatter, level=logging.INFO)
288
 
289
+ demo.launch(inbrowser=True)
requirements.txt CHANGED
@@ -3,3 +3,4 @@ numpy
3
 
4
  huggingface_hub
5
  sherpa-onnx>=1.9.21
 
 
3
 
4
  huggingface_hub
5
  sherpa-onnx>=1.9.21
6
+ gradio
webui.bat ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+
3
+ :: The original source of the webui.bat file is stable-diffusion-webui
4
+ :: Modified and enhanced by Gemini with features for venv management and requirements handling.
5
+
6
+ :: --------- Configuration ---------
7
+ set COMMANDLINE_ARGS=
8
+ :: Define the name of the Launch application
9
+ set APPLICATION_NAME=app.py
10
+ :: Define the name of the virtual environment directory
11
+ set VENV_NAME=venv
12
+ :: Set to 1 to always attempt to update packages from requirements.txt on every launch
13
+ set ALWAYS_UPDATE_REQS=0
14
+ :: ---------------------------------
15
+
16
+
17
+ :: Set PYTHON executable if not already defined
18
+ if not defined PYTHON (set PYTHON=python)
19
+ :: Set VENV_DIR using VENV_NAME if not already defined
20
+ if not defined VENV_DIR (set "VENV_DIR=%~dp0%VENV_NAME%")
21
+
22
+ mkdir tmp 2>NUL
23
+
24
+ :: Check if Python is callable
25
+ %PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
26
+ if %ERRORLEVEL% == 0 goto :check_pip
27
+ echo Couldn't launch python
28
+ goto :show_stdout_stderr
29
+
30
+ :check_pip
31
+ :: Check if pip is available
32
+ %PYTHON% -mpip --help >tmp/stdout.txt 2>tmp/stderr.txt
33
+ if %ERRORLEVEL% == 0 goto :start_venv
34
+ :: If pip is not available and PIP_INSTALLER_LOCATION is set, try to install pip
35
+ if "%PIP_INSTALLER_LOCATION%" == "" goto :show_stdout_stderr
36
+ %PYTHON% "%PIP_INSTALLER_LOCATION%" >tmp/stdout.txt 2>tmp/stderr.txt
37
+ if %ERRORLEVEL% == 0 goto :start_venv
38
+ echo Couldn't install pip
39
+ goto :show_stdout_stderr
40
+
41
+ :start_venv
42
+ :: Skip venv creation/activation if VENV_DIR is explicitly set to "-"
43
+ if ["%VENV_DIR%"] == ["-"] goto :skip_venv_entirely
44
+ :: Skip venv creation/activation if SKIP_VENV is set to "1"
45
+ if ["%SKIP_VENV%"] == ["1"] goto :skip_venv_entirely
46
+
47
+ :: Check if the venv already exists by looking for Python.exe in its Scripts directory
48
+ dir "%VENV_DIR%\Scripts\Python.exe" >tmp/stdout.txt 2>tmp/stderr.txt
49
+ if %ERRORLEVEL% == 0 goto :activate_venv_and_maybe_update
50
+
51
+ :: Venv does not exist, create it
52
+ echo Virtual environment not found in "%VENV_DIR%". Creating a new one.
53
+ for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
54
+ echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%
55
+ %PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
56
+ if %ERRORLEVEL% NEQ 0 (
57
+ echo Unable to create venv in directory "%VENV_DIR%"
58
+ goto :show_stdout_stderr
59
+ )
60
+ echo Venv created.
61
+
62
+ :: Install requirements for the first time if venv was just created
63
+ :: This section handles the initial installation of packages from requirements.txt
64
+ :: immediately after a new virtual environment is created.
65
+ echo Checking for requirements.txt for initial setup in %~dp0
66
+ if exist "%~dp0requirements.txt" (
67
+ echo Found requirements.txt, attempting to install for initial setup...
68
+ call "%VENV_DIR%\Scripts\activate.bat"
69
+ echo Installing packages from requirements.txt ^(initial setup^)...
70
+ "%VENV_DIR%\Scripts\python.exe" -m pip install -r "%~dp0requirements.txt"
71
+ if %ERRORLEVEL% NEQ 0 (
72
+ echo Failed to install requirements during initial setup. Please check the output above.
73
+ pause
74
+ goto :show_stdout_stderr_custom_pip_initial
75
+ )
76
+ echo Initial requirements installed successfully.
77
+ call "%VENV_DIR%\Scripts\deactivate.bat"
78
+ ) else (
79
+ echo No requirements.txt found for initial setup, skipping package installation.
80
+ )
81
+ goto :activate_venv_and_maybe_update
82
+
83
+
84
+ :activate_venv_and_maybe_update
85
+ :: This label is reached if the venv exists or was just created.
86
+ :: Set PYTHON to point to the venv's Python interpreter.
87
+ set PYTHON="%VENV_DIR%\Scripts\Python.exe"
88
+ echo Activating venv: %PYTHON%
89
+
90
+ :: Always update requirements if ALWAYS_UPDATE_REQS is 1
91
+ :: This section allows for updating packages from requirements.txt on every launch
92
+ :: if the ALWAYS_UPDATE_REQS variable is set to 1.
93
+ if defined ALWAYS_UPDATE_REQS (
94
+ if "%ALWAYS_UPDATE_REQS%"=="1" (
95
+ echo ALWAYS_UPDATE_REQS is enabled.
96
+ if exist "%~dp0requirements.txt" (
97
+ echo Attempting to update packages from requirements.txt...
98
+ REM No need to call activate.bat here again, PYTHON is already set to the venv's python
99
+ %PYTHON% -m pip install -r "%~dp0requirements.txt"
100
+ if %ERRORLEVEL% NEQ 0 (
101
+ echo Failed to update requirements. Please check the output above.
102
+ pause
103
+ goto :endofscript
104
+ )
105
+ echo Requirements updated successfully.
106
+ ) else (
107
+ echo ALWAYS_UPDATE_REQS is enabled, but no requirements.txt found. Skipping update.
108
+ )
109
+ ) else (
110
+ echo ALWAYS_UPDATE_REQS is not enabled or not set to 1. Skipping routine update.
111
+ )
112
+ )
113
+
114
+ goto :launch
115
+
116
+ :skip_venv_entirely
117
+ :: This label is reached if venv usage is explicitly skipped.
118
+ echo Skipping venv.
119
+ goto :launch
120
+
121
+ :launch
122
+ :: Launch the main application
123
+ echo Launching Web UI with arguments: %COMMANDLINE_ARGS% %*
124
+ %PYTHON% %APPLICATION_NAME% %COMMANDLINE_ARGS% %*
125
+ echo Launch finished.
126
+ pause
127
+ exit /b
128
+
129
+ :show_stdout_stderr_custom_pip_initial
130
+ :: Custom error handler for failures during the initial pip install process.
131
+ echo.
132
+ echo exit code ^(pip initial install^): %errorlevel%
133
+ echo Errors during initial pip install. See output above.
134
+ echo.
135
+ echo Launch unsuccessful. Exiting.
136
+ pause
137
+ exit /b
138
+
139
+
140
+ :show_stdout_stderr
141
+ :: General error handler: displays stdout and stderr from the tmp directory.
142
+ echo.
143
+ echo exit code: %errorlevel%
144
+
145
+ for /f %%i in ("tmp\stdout.txt") do set size=%%~zi
146
+ if %size% equ 0 goto :show_stderr
147
+ echo.
148
+ echo stdout:
149
+ type tmp\stdout.txt
150
+
151
+ :show_stderr
152
+ for /f %%i in ("tmp\stderr.txt") do set size=%%~zi
153
+ if %size% equ 0 goto :endofscript
154
+ echo.
155
+ echo stderr:
156
+ type tmp\stderr.txt
157
+
158
+ :endofscript
159
+ echo.
160
+ echo Launch unsuccessful. Exiting.
161
+ pause
162
+ exit /b