File size: 1,911 Bytes
397b4ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""Runtime paths and shared execution controls for the Space."""
import os
import tempfile
import threading
import warnings
from pathlib import Path


APP_ROOT = Path(__file__).resolve().parent


def _usable_root(path: Path, *, warn: bool = False) -> Path | None:
    try:
        path.mkdir(parents=True, exist_ok=True)
        probe = path / ".write_probe"
        probe.write_text("ok", encoding="utf-8")
        probe.unlink(missing_ok=True)
        return path
    except OSError as exc:
        if warn:
            warnings.warn(f"Runtime storage path is not writable: {path} ({exc})")
        return None


def _select_storage_root() -> Path:
    configured = (
        os.environ.get("MOMSVOICE_STORAGE_DIR")
        or os.environ.get("SPACE_STORAGE_DIR")
    )
    candidates: list[tuple[Path, bool]] = []
    if configured:
        candidates.append((Path(configured).expanduser(), True))
    candidates.extend([
        (Path("/data") / "momsvoice", False),
        (APP_ROOT, True),
        (Path(tempfile.gettempdir()) / "momsvoice", True),
    ])

    for candidate, warn in candidates:
        usable = _usable_root(candidate, warn=warn)
        if usable is not None:
            return usable

    raise RuntimeError("No writable runtime storage path is available.")


STORAGE_ROOT = _select_storage_root()

VOICE_PROFILE_DIR = STORAGE_ROOT / "Voice_Profile"
AUDIO_CACHE_DIR = STORAGE_ROOT / "audio_cache"
SAMPLE_SOUNDS_DIR = STORAGE_ROOT / "sample_sounds"

for _path in (VOICE_PROFILE_DIR, AUDIO_CACHE_DIR, SAMPLE_SOUNDS_DIR):
    _path.mkdir(parents=True, exist_ok=True)


# Serializes GPU-heavy model calls across Gradio events and background pregen
# threads. This keeps the Space responsive under hackathon demo traffic.
GPU_INFERENCE_LOCK = threading.RLock()


def gradio_allowed_paths() -> list[str]:
    return [
        str(APP_ROOT / "assets"),
        str(SAMPLE_SOUNDS_DIR),
    ]