Spaces:
Running on T4
Running on T4
| #!/usr/bin/env python3 | |
| """Post-install setup for platform-specific runtime dependencies. | |
| 1. **Windows: VC++ Redistributable** β PyTorch's native DLLs (c10.dll, | |
| torch_cpu.dll, etc.) link against vcruntime140.dll and msvcp140.dll from | |
| the Microsoft Visual C++ 2015-2022 Redistributable. Fresh Windows installs | |
| (especially debloated/LTSC-style) don't ship it. We detect and auto-install | |
| it silently before any `import torch` can fail. | |
| 2. **CUDA: cuDNN 8 compat** β Ensures cuDNN 8 libraries are available for | |
| CTranslate2 (faster-whisper / WhisperX) alongside PyTorch 2.8+'s cuDNN 9. | |
| Run automatically as part of `bun run setup:api` β no user action required. | |
| Cross-platform: | |
| - Linux: cuDNN 8 compat (.so.8 libs) | |
| - Windows: VC++ Redistributable + cuDNN 8 compat (.dll libs) | |
| - macOS: skipped (no CUDA) | |
| """ | |
| import os | |
| import sys | |
| import subprocess | |
| import glob | |
| if sys.platform == "win32" and hasattr(sys.stdout, "reconfigure"): | |
| sys.stdout.reconfigure(encoding="utf-8") | |
| # ββ Windows: VC++ Redistributable βββββββββββββββββββββββββββββββββββββββββ | |
| def _ensure_vcredist_windows(): | |
| """Check for and install the VC++ 2015-2022 Redistributable on Windows. | |
| PyTorch's native libraries (c10.dll, torch_cpu.dll, etc.) are built with | |
| MSVC and dynamically link against vcruntime140.dll + msvcp140.dll. These | |
| ship with Visual Studio / Build Tools but are NOT part of Windows itself. | |
| On a fresh or debloated install the very first `import torch` crashes with: | |
| OSError: [WinError 126] The specified module could not be found. | |
| Error loading ...\\torch\\lib\\c10.dll or one of its dependencies. | |
| This function silently downloads and installs the official x64 redist | |
| package from Microsoft if the runtime DLLs are missing. | |
| """ | |
| if sys.platform != "win32": | |
| return | |
| # Check if vcruntime140.dll is already loadable | |
| import ctypes | |
| try: | |
| ctypes.WinDLL("vcruntime140.dll") | |
| print("β VC++ Redistributable: already installed") | |
| return | |
| except OSError: | |
| pass | |
| print("β VC++ Redistributable not found β installing (required for PyTorch)...") | |
| import tempfile | |
| import urllib.request | |
| vc_url = "https://aka.ms/vs/17/release/vc_redist.x64.exe" | |
| installer = os.path.join(tempfile.gettempdir(), "vc_redist.x64.exe") | |
| try: | |
| # Download | |
| print(" Downloading VC++ Redistributable...") | |
| urllib.request.urlretrieve(vc_url, installer) | |
| # Silent install (/install /quiet /norestart) | |
| print(" Installing silently...") | |
| result = subprocess.run( | |
| [installer, "/install", "/quiet", "/norestart"], | |
| timeout=120, | |
| capture_output=True, | |
| ) | |
| # Verify it worked | |
| try: | |
| ctypes.WinDLL("vcruntime140.dll") | |
| print("β VC++ Redistributable: installed successfully") | |
| except OSError: | |
| # Exit code 3010 = success but reboot required | |
| if result.returncode == 3010: | |
| print("β VC++ Redistributable: installed (reboot recommended)") | |
| else: | |
| print(f"β VC++ Redistributable: install may have failed (exit code {result.returncode})") | |
| print(" Manual install: https://aka.ms/vs/17/release/vc_redist.x64.exe") | |
| except Exception as e: | |
| print(f"β VC++ Redistributable: auto-install failed: {e}") | |
| print(" Manual install: https://aka.ms/vs/17/release/vc_redist.x64.exe") | |
| finally: | |
| # Clean up installer | |
| try: | |
| os.remove(installer) | |
| except OSError: | |
| pass | |
| # ββ cuDNN 8 compat ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _find_compat_dir(): | |
| """Return the cudnn8_compat target directory, auto-detecting venv layout.""" | |
| script_dir = os.path.dirname(os.path.abspath(__file__)) | |
| project_root = os.path.dirname(script_dir) | |
| venv_dir = os.path.join(project_root, ".venv") | |
| if not os.path.isdir(venv_dir): | |
| return None | |
| if sys.platform == "win32": | |
| # Windows: .venv/Lib/site-packages/ | |
| sp = os.path.join(venv_dir, "Lib", "site-packages", "cudnn8_compat") | |
| else: | |
| # Linux: .venv/lib/pythonX.Y/site-packages/ | |
| pyver = f"python{sys.version_info.major}.{sys.version_info.minor}" | |
| sp = os.path.join(venv_dir, "lib", pyver, "site-packages", "cudnn8_compat") | |
| return sp | |
| def _cudnn8_lib_dir(compat_dir): | |
| """Return the cuDNN lib subdirectory within the compat install.""" | |
| if sys.platform == "win32": | |
| return os.path.join(compat_dir, "nvidia", "cudnn", "bin") | |
| return os.path.join(compat_dir, "nvidia", "cudnn", "lib") | |
| def _count_cudnn8_libs(lib_dir): | |
| """Count cuDNN 8 shared libraries in the given directory.""" | |
| if sys.platform == "win32": | |
| return len(glob.glob(os.path.join(lib_dir, "cudnn*64_8.dll"))) | |
| return len(glob.glob(os.path.join(lib_dir, "libcudnn*.so.8"))) | |
| def main(): | |
| # ββ Step 1: Windows VC++ Redistributable ββββββββββββββββββββββββββββββ | |
| _ensure_vcredist_windows() | |
| # macOS β no CUDA, nothing to do | |
| if sys.platform == "darwin": | |
| return | |
| compat_dir = _find_compat_dir() | |
| if compat_dir is None: | |
| return | |
| lib_dir = _cudnn8_lib_dir(compat_dir) | |
| # Already installed? | |
| if os.path.isdir(lib_dir): | |
| n = _count_cudnn8_libs(lib_dir) | |
| if n >= 5: | |
| print(f"β cuDNN 8 compat: {n} libraries ready") | |
| return | |
| # Check if CUDA is available before installing GPU-only libs | |
| try: | |
| result = subprocess.run( | |
| [sys.executable, "-c", "import torch; print(torch.cuda.is_available())"], | |
| capture_output=True, text=True, timeout=30, | |
| ) | |
| if result.stdout.strip() != "True": | |
| print("β No CUDA β cuDNN 8 compat not needed") | |
| return | |
| except Exception: | |
| pass # Can't detect CUDA β install anyway, it's harmless on CPU | |
| print("β Installing cuDNN 8 compatibility libraries for CTranslate2...") | |
| try: | |
| subprocess.run( | |
| [ | |
| sys.executable, "-m", "pip", "install", | |
| "--no-deps", "--target", compat_dir, | |
| "nvidia-cudnn-cu12==8.9.7.29", | |
| ], | |
| check=True, | |
| capture_output=True, | |
| text=True, | |
| timeout=180, | |
| ) | |
| n = _count_cudnn8_libs(lib_dir) | |
| print(f"β cuDNN 8 installed: {n} libraries") | |
| except subprocess.CalledProcessError as e: | |
| print(f"β cuDNN 8 install failed (transcription may not work on CUDA):") | |
| print(f" {(e.stderr or '')[:300]}") | |
| except Exception as e: | |
| print(f"β cuDNN 8 install skipped: {e}") | |
| if __name__ == "__main__": | |
| main() | |