Spaces:
Runtime error
Runtime error
Upload app.py with huggingface_hub
Browse files
app.py
CHANGED
|
@@ -49,8 +49,8 @@ def _embed(audio_array: np.ndarray, sr: int, max_sec: int) -> np.ndarray:
|
|
| 49 |
return out.embeddings.squeeze().numpy()
|
| 50 |
|
| 51 |
|
| 52 |
-
def _fetch_audio_urls(repo_id: str, n: int, token: str | None) -> list[str]:
|
| 53 |
-
"""Get direct audio URLs via datasets-server
|
| 54 |
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
| 55 |
resp = requests.get(
|
| 56 |
f"{DATASETS_SERVER}/rows",
|
|
@@ -58,13 +58,26 @@ def _fetch_audio_urls(repo_id: str, n: int, token: str | None) -> list[str]:
|
|
| 58 |
headers=headers,
|
| 59 |
timeout=30,
|
| 60 |
)
|
| 61 |
-
resp.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
urls = []
|
| 63 |
-
for row in
|
| 64 |
audio = row["row"].get("audio", {})
|
| 65 |
if isinstance(audio, dict) and "src" in audio:
|
| 66 |
urls.append(audio["src"])
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
|
| 70 |
def _download_one(url: str, token: str | None, max_sec: int) -> tuple[np.ndarray, dict]:
|
|
@@ -90,31 +103,57 @@ def _download_one(url: str, token: str | None, max_sec: int) -> tuple[np.ndarray
|
|
| 90 |
}
|
| 91 |
|
| 92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
def _process_repo(
|
| 94 |
repo: str, n_samples: int, audio_sec: int, token: str | None
|
| 95 |
) -> tuple[str, np.ndarray | None, str]:
|
| 96 |
t0 = time.time()
|
| 97 |
try:
|
| 98 |
-
urls = _fetch_audio_urls(repo, n_samples, token)
|
| 99 |
-
if not urls:
|
| 100 |
-
return repo, None, f"{repo}: no audio URLs from datasets-server"
|
| 101 |
fetch_ms = int((time.time() - t0) * 1000)
|
| 102 |
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
return repo, np.mean(embs, axis=0), log
|
| 119 |
|
| 120 |
except Exception as exc:
|
|
|
|
| 49 |
return out.embeddings.squeeze().numpy()
|
| 50 |
|
| 51 |
|
| 52 |
+
def _fetch_audio_urls(repo_id: str, n: int, token: str | None) -> tuple[list[str], str]:
|
| 53 |
+
"""Get direct audio URLs via datasets-server. Returns (urls, debug_info)."""
|
| 54 |
headers = {"Authorization": f"Bearer {token}"} if token else {}
|
| 55 |
resp = requests.get(
|
| 56 |
f"{DATASETS_SERVER}/rows",
|
|
|
|
| 58 |
headers=headers,
|
| 59 |
timeout=30,
|
| 60 |
)
|
| 61 |
+
if not resp.ok:
|
| 62 |
+
return [], f"datasets-server {resp.status_code}"
|
| 63 |
+
|
| 64 |
+
rows = resp.json().get("rows", [])
|
| 65 |
+
if not rows:
|
| 66 |
+
return [], "datasets-server: empty rows"
|
| 67 |
+
|
| 68 |
+
# Inspect actual audio field structure for debugging
|
| 69 |
+
sample_audio = rows[0]["row"].get("audio", {})
|
| 70 |
+
audio_keys = list(sample_audio.keys()) if isinstance(sample_audio, dict) else type(sample_audio).__name__
|
| 71 |
+
|
| 72 |
urls = []
|
| 73 |
+
for row in rows:
|
| 74 |
audio = row["row"].get("audio", {})
|
| 75 |
if isinstance(audio, dict) and "src" in audio:
|
| 76 |
urls.append(audio["src"])
|
| 77 |
+
|
| 78 |
+
if not urls:
|
| 79 |
+
return [], f"datasets-server: no src in audio field (keys={audio_keys})"
|
| 80 |
+
return urls, f"datasets-server ok (audio keys={audio_keys})"
|
| 81 |
|
| 82 |
|
| 83 |
def _download_one(url: str, token: str | None, max_sec: int) -> tuple[np.ndarray, dict]:
|
|
|
|
| 103 |
}
|
| 104 |
|
| 105 |
|
| 106 |
+
def _streaming_fallback(repo: str, n_samples: int, audio_sec: int, token: str | None) -> list[np.ndarray]:
|
| 107 |
+
"""Fallback: use datasets streaming when datasets-server is unavailable."""
|
| 108 |
+
from datasets import load_dataset, Audio as HFAudio
|
| 109 |
+
ds = load_dataset(repo, split="train", streaming=True, token=token)
|
| 110 |
+
ds = ds.cast_column("audio", HFAudio(decode=False))
|
| 111 |
+
embs = []
|
| 112 |
+
for j, row in enumerate(ds):
|
| 113 |
+
if j >= n_samples:
|
| 114 |
+
break
|
| 115 |
+
raw = row["audio"]
|
| 116 |
+
audio_bytes = raw.get("bytes") or open(raw["path"], "rb").read()
|
| 117 |
+
audio_array, sr = sf.read(io.BytesIO(audio_bytes))
|
| 118 |
+
embs.append(_embed(audio_array, sr, audio_sec))
|
| 119 |
+
return embs
|
| 120 |
+
|
| 121 |
+
|
| 122 |
def _process_repo(
|
| 123 |
repo: str, n_samples: int, audio_sec: int, token: str | None
|
| 124 |
) -> tuple[str, np.ndarray | None, str]:
|
| 125 |
t0 = time.time()
|
| 126 |
try:
|
| 127 |
+
urls, api_debug = _fetch_audio_urls(repo, n_samples, token)
|
|
|
|
|
|
|
| 128 |
fetch_ms = int((time.time() - t0) * 1000)
|
| 129 |
|
| 130 |
+
if urls:
|
| 131 |
+
# Fast path: parallel downloads via datasets-server URLs
|
| 132 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=len(urls)) as ex:
|
| 133 |
+
futures = [ex.submit(_download_one, u, token, audio_sec) for u in urls]
|
| 134 |
+
results = [f.result() for f in futures]
|
| 135 |
+
embs = [r[0] for r in results]
|
| 136 |
+
s = results[0][1]
|
| 137 |
+
total_ms = int((time.time() - t0) * 1000)
|
| 138 |
+
log = (
|
| 139 |
+
f"{repo.split('/')[-1]}: "
|
| 140 |
+
f"api={fetch_ms}ms dl={s['dl_ms']}ms "
|
| 141 |
+
f"decode={s['decode_ms']}ms embed={s['embed_ms']}ms "
|
| 142 |
+
f"total={total_ms}ms ({s['size_kb']}KB/file) [{api_debug}]"
|
| 143 |
+
)
|
| 144 |
+
else:
|
| 145 |
+
# Slow fallback: streaming (downloads parquet shard)
|
| 146 |
+
t1 = time.time()
|
| 147 |
+
embs = _streaming_fallback(repo, n_samples, audio_sec, token)
|
| 148 |
+
total_ms = int((time.time() - t0) * 1000)
|
| 149 |
+
log = (
|
| 150 |
+
f"{repo.split('/')[-1]}: streaming fallback "
|
| 151 |
+
f"total={total_ms}ms [reason: {api_debug}]"
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
if not embs:
|
| 155 |
+
return repo, None, f"{repo}: no audio samples extracted"
|
| 156 |
+
|
| 157 |
return repo, np.mean(embs, axis=0), log
|
| 158 |
|
| 159 |
except Exception as exc:
|