""" Static sample audio and scene image for the Examples tab. Files are read from ``examples/`` when present locally. Missing assets are downloaded from the FFASR Hub bucket (``examples/``) and cached there. Do not commit ``.wav`` / ``.png`` to the Space git repo — Hugging Face rejects binary pushes unless Git LFS is configured. Upload assets to the bucket instead. """ from __future__ import annotations import os import shutil from pathlib import Path EXAMPLES_DIR = Path(__file__).resolve().parent / "examples" # Bucket prefix inside FFASR_BUCKET_ID (override with FFASR_EXAMPLES_BUCKET_PREFIX). DEFAULT_BUCKET_PREFIX = "examples/" SCENE_IMAGE = "scene.png" SAMPLE_FILES: dict[str, list[str]] = { "dry": ["dry_speech_example_1.wav"], "high_snr": ["high_snr_example_1.wav"], "mid_snr": ["mid_snr_example_1.wav"], "low_snr": ["low_snr_example_1.wav"], } ALL_ASSET_NAMES: list[str] = [SCENE_IMAGE] + [ name for names in SAMPLE_FILES.values() for name in names ] def _bucket_prefix() -> str: raw = (os.environ.get("FFASR_EXAMPLES_BUCKET_PREFIX") or DEFAULT_BUCKET_PREFIX).strip() return raw if raw.endswith("/") else f"{raw}/" def _local_path(name: str) -> Path: return EXAMPLES_DIR / name def _resolve(name: str) -> Path | None: path = _local_path(name) return path if path.is_file() else None def _download_from_bucket(name: str) -> bool: try: from storage import STORAGE_BACKEND, download_bucket_file if STORAGE_BACKEND != "hf_bucket": return False bucket_path = f"{_bucket_prefix()}{name}" downloaded = Path(download_bucket_file(bucket_path)) EXAMPLES_DIR.mkdir(parents=True, exist_ok=True) dest = _local_path(name) shutil.copy2(downloaded, dest) return dest.is_file() except Exception: return False def ensure_assets() -> None: """Ensure example files exist locally, fetching missing ones from the bucket.""" EXAMPLES_DIR.mkdir(parents=True, exist_ok=True) for name in ALL_ASSET_NAMES: if _resolve(name): continue _download_from_bucket(name) def sample_paths(condition: str) -> list[str | None]: """Return absolute paths for each clip in a condition (``None`` if missing).""" names = SAMPLE_FILES.get(condition, []) return [str(p) if (p := _resolve(n)) else None for n in names] def scene_image_path() -> str | None: p = _resolve(SCENE_IMAGE) return str(p) if p else None def missing_files() -> list[str]: return [n for n in ALL_ASSET_NAMES if not _resolve(n)] def status() -> tuple[bool, str]: missing = missing_files() if not missing: return True, "All example clips and the scene screenshot are available." prefix = _bucket_prefix() return ( False, "Missing example files (not in examples/ and not in the Hub bucket):\n• " + "\n• ".join(sorted(set(missing))) + f"\n\nUpload them to the bucket under `{prefix}` (see examples/README.md).", ) def status_html() -> str: ready, msg = status() color = "#38BFA1" if ready else "#E8A838" title = "Examples ready" if ready else "Some example files are missing" body = msg.replace("\n", "
") return ( f"
" f"{title}
" f"{body}
" )