From 6c13604664b7b88ec8f020b7547302b5eee0017d Mon Sep 17 00:00:00 2001 From: Nose Date: Fri, 9 Jan 2026 16:02:49 -0800 Subject: [PATCH] f --- scripts/bootstrap.py | 13 +++++--- tool/playwright.py | 73 +++++++++++++++++++++++++++++++++----------- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/scripts/bootstrap.py b/scripts/bootstrap.py index 16d8675..ba8e7c0 100644 --- a/scripts/bootstrap.py +++ b/scripts/bootstrap.py @@ -8,6 +8,10 @@ downloads Playwright browser binaries by running `python -m playwright install`. By default this script installs **Chromium** only to conserve space; pass `--browsers all` to install all supported engines (chromium, firefox, webkit). +FFmpeg: The project includes ffmpeg binaries for Windows (in MPV/ffmpeg). On Linux/macOS, +install ffmpeg using your system package manager (apt install ffmpeg, brew install ffmpeg, etc.). +ffmpeg-python is installed as a dependency, but requires ffmpeg itself to be on your PATH. + Note: This Python script is the canonical installer for the project — prefer running `python ./scripts/bootstrap.py` locally. The platform scripts (`scripts/bootstrap.ps1` and `scripts/bootstrap.sh`) are now thin wrappers @@ -641,7 +645,7 @@ def main() -> int: if not playwright_package_installed(): if not args.quiet: print("'playwright' package not found; installing it via pip...") - run([sys.executable, "-m", "pip", "install", "playwright"]) + run([sys.executable, "-m", "pip", "install", "--no-cache-dir", "playwright"]) if not args.quiet: print( @@ -668,6 +672,7 @@ def main() -> int: "pip", "install", "--upgrade", + "--no-cache-dir", "pip", "setuptools", "wheel", @@ -686,13 +691,13 @@ def main() -> int: print( f"Installing Python dependencies into local venv from {req_file}..." ) - run([str(venv_python), "-m", "pip", "install", "-r", str(req_file)]) + run([str(venv_python), "-m", "pip", "install", "--no-cache-dir", "-r", str(req_file)]) if not args.no_playwright: if not playwright_package_installed(): if not args.quiet: print("'playwright' package not installed in venv; installing it...") - run([str(venv_python), "-m", "pip", "install", "playwright"]) + run([str(venv_python), "-m", "pip", "install", "--no-cache-dir", "playwright"]) if not args.quiet: print( @@ -711,7 +716,7 @@ def main() -> int: # Install the project into the local venv (editable mode is the default, opinionated) if not args.quiet: print("Installing project into local venv (editable mode)") - run([str(venv_python), "-m", "pip", "install", "-e", str(repo_root / "scripts")]) + run([str(venv_python), "-m", "pip", "install", "--no-cache-dir", "-e", str(repo_root / "scripts")]) # Verify top-level 'CLI' import and, if missing, attempt to make it available if not args.quiet: diff --git a/tool/playwright.py b/tool/playwright.py index 48de954..c05cecf 100644 --- a/tool/playwright.py +++ b/tool/playwright.py @@ -174,30 +174,49 @@ class PlaywrightTool: ignore_https = bool(_get("ignore_https_errors", defaults.ignore_https_errors)) # Try to find ffmpeg: config override, environment variable, bundled, then system + # This checks if ffmpeg is actually available (not just the path to it) ffmpeg_path: Optional[str] = None config_ffmpeg = _get("ffmpeg_path", None) + if config_ffmpeg: - ffmpeg_path = str(config_ffmpeg).strip() - else: + # User explicitly configured ffmpeg path + candidate = str(config_ffmpeg).strip() + if Path(candidate).exists(): + ffmpeg_path = candidate + else: + debug(f"Configured ffmpeg path does not exist: {candidate}") + + if not ffmpeg_path: # Check environment variable (supports project ffmpeg) env_ffmpeg = os.environ.get("PLAYWRIGHT_FFMPEG_PATH") - if env_ffmpeg: + if env_ffmpeg and Path(env_ffmpeg).exists(): ffmpeg_path = env_ffmpeg + elif env_ffmpeg: + debug(f"PLAYWRIGHT_FFMPEG_PATH set but path does not exist: {env_ffmpeg}") + + if not ffmpeg_path: + # Try to find bundled ffmpeg in the project (Windows-only, in MPV/ffmpeg/bin) + try: + repo_root = Path(__file__).resolve().parent.parent + bundled_ffmpeg = repo_root / "MPV" / "ffmpeg" / "bin" + if bundled_ffmpeg.exists(): + ffmpeg_exe = bundled_ffmpeg / ("ffmpeg.exe" if os.name == "nt" else "ffmpeg") + if ffmpeg_exe.exists(): + ffmpeg_path = str(ffmpeg_exe) + debug(f"Found bundled ffmpeg at: {ffmpeg_path}") + except Exception as e: + debug(f"Error checking for bundled ffmpeg: {e}") + + if not ffmpeg_path: + # Try system ffmpeg if bundled not found + system_ffmpeg = shutil.which("ffmpeg") + if system_ffmpeg: + ffmpeg_path = system_ffmpeg + debug(f"Found system ffmpeg at: {ffmpeg_path}") else: - # Try to find bundled ffmpeg in the project (if available) - try: - repo_root = Path(__file__).resolve().parent.parent - bundled_ffmpeg = repo_root / "MPV" / "ffmpeg" / "bin" - if bundled_ffmpeg.exists(): - ffmpeg_exe = bundled_ffmpeg / ("ffmpeg.exe" if os.name == "nt" else "ffmpeg") - if ffmpeg_exe.exists(): - ffmpeg_path = str(ffmpeg_exe) - except Exception: - pass - - # Try system ffmpeg if bundled not found - if not ffmpeg_path: - ffmpeg_path = shutil.which("ffmpeg") + # ffmpeg not found - log a debug message but don't fail + # ffmpeg-python may still work with system installation, or user might not need it + debug("ffmpeg not found on PATH. For best compatibility, install ffmpeg: Windows (use bundled or choco install ffmpeg), macOS (brew install ffmpeg), Linux (apt install ffmpeg or equivalent)") return PlaywrightDefaults( browser=browser, @@ -219,6 +238,26 @@ class PlaywrightTool: "playwright is required; install with: pip install playwright; then: playwright install" ) + def ffmpeg_available(self) -> bool: + """Check if ffmpeg is available on the system.""" + return bool(self.defaults.ffmpeg_path) + + def require_ffmpeg(self) -> None: + """Require ffmpeg to be available; raise a helpful error if not. + + This should be called before operations that need ffmpeg (e.g., video recording). + """ + if not self.ffmpeg_available(): + raise RuntimeError( + "ffmpeg is required but not found on your system.\n" + "Install it using:\n" + " Windows: choco install ffmpeg (if using Chocolatey) or use the bundled version in MPV/ffmpeg\n" + " macOS: brew install ffmpeg\n" + " Linux: apt install ffmpeg (Ubuntu/Debian) or equivalent for your distribution\n" + "\n" + "Or set the PLAYWRIGHT_FFMPEG_PATH environment variable to point to your ffmpeg executable." + ) + @contextlib.contextmanager def open_page( self,