Spaces:
Runtime error
Runtime error
Remove ZIP download feature to fix import error
Browse files
README.md
CHANGED
|
@@ -31,7 +31,6 @@ Spells collected:
|
|
| 31 |
- The app will save any provided recordings to `recordings/` as 16 kHz mono WAVs named: `<spell>_<username>_<timestamp>.wav`.
|
| 32 |
- A live counter shows how many spells are selected (recorded/uploaded) before submitting.
|
| 33 |
- A CSV log is written to `recordings/log.csv` with columns: `timestamp_ms, session_id, username, spell, filename`.
|
| 34 |
-
- You can prepare a ZIP of this session's saved files if you enter the correct download key.
|
| 35 |
|
| 36 |
## Run locally
|
| 37 |
|
|
@@ -62,14 +61,6 @@ Notes:
|
|
| 62 |
- Microphone recording is enabled in the browser; no need to upload.
|
| 63 |
- If you need more durable storage or collaboration, consider pushing saved WAVs to a dataset repo programmatically.
|
| 64 |
|
| 65 |
-
### Enable password-protected ZIP download
|
| 66 |
-
|
| 67 |
-
Set a Space secret so only people with the key can generate a ZIP of their session files:
|
| 68 |
-
|
| 69 |
-
- Go to your Space → Settings → Variables and secrets
|
| 70 |
-
- Add a secret named `ZIP_DOWNLOAD_KEY` with your chosen value
|
| 71 |
-
- In the app UI, paste that key into the "Download Key" field before clicking "Prepare ZIP"
|
| 72 |
-
|
| 73 |
## Privacy and consent
|
| 74 |
- Only collect voices from people who consent to being recorded.
|
| 75 |
- Consider informing contributors how their audio will be used and stored.
|
|
|
|
| 31 |
- The app will save any provided recordings to `recordings/` as 16 kHz mono WAVs named: `<spell>_<username>_<timestamp>.wav`.
|
| 32 |
- A live counter shows how many spells are selected (recorded/uploaded) before submitting.
|
| 33 |
- A CSV log is written to `recordings/log.csv` with columns: `timestamp_ms, session_id, username, spell, filename`.
|
|
|
|
| 34 |
|
| 35 |
## Run locally
|
| 36 |
|
|
|
|
| 61 |
- Microphone recording is enabled in the browser; no need to upload.
|
| 62 |
- If you need more durable storage or collaboration, consider pushing saved WAVs to a dataset repo programmatically.
|
| 63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
## Privacy and consent
|
| 65 |
- Only collect voices from people who consent to being recorded.
|
| 66 |
- Consider informing contributors how their audio will be used and stored.
|
app.py
CHANGED
|
@@ -4,7 +4,6 @@ import time
|
|
| 4 |
import math
|
| 5 |
import csv
|
| 6 |
import uuid
|
| 7 |
-
import zipfile
|
| 8 |
from typing import List, Tuple, Optional
|
| 9 |
|
| 10 |
import numpy as np
|
|
@@ -15,8 +14,6 @@ from scipy.signal import resample_poly
|
|
| 15 |
# Output directory for saved recordings
|
| 16 |
OUT_DIR = "recordings"
|
| 17 |
os.makedirs(OUT_DIR, exist_ok=True)
|
| 18 |
-
ZIP_DIR = os.path.join(OUT_DIR, "zips")
|
| 19 |
-
os.makedirs(ZIP_DIR, exist_ok=True)
|
| 20 |
LOG_CSV = os.path.join(OUT_DIR, "log.csv")
|
| 21 |
|
| 22 |
# Fixed target sample rate for ML training
|
|
@@ -170,25 +167,6 @@ def count_selected(
|
|
| 170 |
return f"Selected: {n}/6"
|
| 171 |
|
| 172 |
|
| 173 |
-
def prepare_zip(download_key: str, session_files: List[str]) -> Tuple[Optional[str], str]:
|
| 174 |
-
expected = os.getenv("ZIP_DOWNLOAD_KEY", "")
|
| 175 |
-
if not expected:
|
| 176 |
-
return None, "Download disabled: ZIP_DOWNLOAD_KEY not set in environment."
|
| 177 |
-
if (download_key or "").strip() != expected:
|
| 178 |
-
return None, "Invalid key. Please enter the correct download key."
|
| 179 |
-
files = [p for p in (session_files or []) if p and os.path.exists(p)]
|
| 180 |
-
if not files:
|
| 181 |
-
return None, "No files in this session to zip. Submit recordings first."
|
| 182 |
-
|
| 183 |
-
session_id = uuid.uuid4().hex[:8]
|
| 184 |
-
ts = int(time.time() * 1000)
|
| 185 |
-
zip_path = os.path.join(ZIP_DIR, f"submissions_{session_id}_{ts}.zip")
|
| 186 |
-
with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
|
| 187 |
-
for f in files:
|
| 188 |
-
zf.write(f, arcname=os.path.basename(f))
|
| 189 |
-
return zip_path, f"Prepared ZIP with {len(files)} files."
|
| 190 |
-
|
| 191 |
-
|
| 192 |
def build_ui() -> gr.Blocks:
|
| 193 |
with gr.Blocks(title="Spell Recorder") as demo:
|
| 194 |
gr.Markdown("""
|
|
@@ -222,14 +200,6 @@ def build_ui() -> gr.Blocks:
|
|
| 222 |
result = gr.Markdown()
|
| 223 |
submitted_count = gr.Number(label="New files saved this submit", value=0)
|
| 224 |
|
| 225 |
-
# Download section (password-gated)
|
| 226 |
-
with gr.Row():
|
| 227 |
-
download_key = gr.Textbox(label="Download Key", type="password", placeholder="Enter key to enable ZIP download")
|
| 228 |
-
with gr.Row():
|
| 229 |
-
zip_btn = gr.Button("Prepare ZIP of my session files")
|
| 230 |
-
zip_file = gr.File(label="Download ZIP", interactive=False)
|
| 231 |
-
zip_status = gr.Markdown()
|
| 232 |
-
|
| 233 |
submit.click(
|
| 234 |
fn=submit_recordings,
|
| 235 |
inputs=[username, lumos, nox, alohomora, wingardium, accio, reparo, session_id, session_files],
|
|
@@ -244,20 +214,12 @@ def build_ui() -> gr.Blocks:
|
|
| 244 |
outputs=[selected_counter],
|
| 245 |
)
|
| 246 |
|
| 247 |
-
# Prepare ZIP on demand (password protected)
|
| 248 |
-
zip_btn.click(
|
| 249 |
-
fn=prepare_zip,
|
| 250 |
-
inputs=[download_key, session_files],
|
| 251 |
-
outputs=[zip_file, zip_status],
|
| 252 |
-
)
|
| 253 |
-
|
| 254 |
gr.Markdown("""
|
| 255 |
Notes:
|
| 256 |
- Files are saved in the app's `recordings/` folder using: `<spell>_<username>_<timestamp>.wav`.
|
| 257 |
- 16 kHz mono WAV is used to make model training consistent.
|
| 258 |
- You don't have to record all spells at once—submit whatever you have.
|
| 259 |
- A CSV log is kept at `recordings/log.csv` with username, spell, timestamp, filename.
|
| 260 |
-
- To enable ZIP download, set the secret env var `ZIP_DOWNLOAD_KEY` in your Space Settings → Variables & secrets.
|
| 261 |
""")
|
| 262 |
|
| 263 |
return demo
|
|
|
|
| 4 |
import math
|
| 5 |
import csv
|
| 6 |
import uuid
|
|
|
|
| 7 |
from typing import List, Tuple, Optional
|
| 8 |
|
| 9 |
import numpy as np
|
|
|
|
| 14 |
# Output directory for saved recordings
|
| 15 |
OUT_DIR = "recordings"
|
| 16 |
os.makedirs(OUT_DIR, exist_ok=True)
|
|
|
|
|
|
|
| 17 |
LOG_CSV = os.path.join(OUT_DIR, "log.csv")
|
| 18 |
|
| 19 |
# Fixed target sample rate for ML training
|
|
|
|
| 167 |
return f"Selected: {n}/6"
|
| 168 |
|
| 169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
def build_ui() -> gr.Blocks:
|
| 171 |
with gr.Blocks(title="Spell Recorder") as demo:
|
| 172 |
gr.Markdown("""
|
|
|
|
| 200 |
result = gr.Markdown()
|
| 201 |
submitted_count = gr.Number(label="New files saved this submit", value=0)
|
| 202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
submit.click(
|
| 204 |
fn=submit_recordings,
|
| 205 |
inputs=[username, lumos, nox, alohomora, wingardium, accio, reparo, session_id, session_files],
|
|
|
|
| 214 |
outputs=[selected_counter],
|
| 215 |
)
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
gr.Markdown("""
|
| 218 |
Notes:
|
| 219 |
- Files are saved in the app's `recordings/` folder using: `<spell>_<username>_<timestamp>.wav`.
|
| 220 |
- 16 kHz mono WAV is used to make model training consistent.
|
| 221 |
- You don't have to record all spells at once—submit whatever you have.
|
| 222 |
- A CSV log is kept at `recordings/log.csv` with username, spell, timestamp, filename.
|
|
|
|
| 223 |
""")
|
| 224 |
|
| 225 |
return demo
|