Files
YT_Download_Script/install_dependencies.py
T
2026-09-13 19:56:37 +01:00

261 lines
8.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Installer for YouTube Downloader dependencies.
Installs: yt-dlp, ffmpeg
Supports: Windows, macOS, Linux (Debian/Ubuntu, Fedora/RHEL, Arch)
"""
import os
import sys
import shutil
import subprocess
import platform
# ── Helpers ────────────────────────────────────────────────────────────────────
def run(cmd: list[str], check=True) -> subprocess.CompletedProcess:
print(f" → {' '.join(cmd)}")
return subprocess.run(cmd, check=check)
def ok(msg: str):
print(f" ✅ {msg}")
def info(msg: str):
print(f" {msg}")
def warn(msg: str):
print(f" ⚠️ {msg}")
def fail(msg: str):
print(f" ❌ {msg}")
sys.exit(1)
def section(title: str):
print(f"\n{'─' * 50}")
print(f" {title}")
print(f"{'─' * 50}")
# ── Platform detection ─────────────────────────────────────────────────────────
OS = platform.system() # 'Windows', 'Darwin', 'Linux'
IS_WIN = OS == "Windows"
IS_MAC = OS == "Darwin"
IS_LINUX = OS == "Linux"
def linux_distro() -> str:
"""Return 'debian', 'fedora', 'arch', or 'unknown'."""
if shutil.which("apt-get"):
return "debian"
if shutil.which("dnf") or shutil.which("yum"):
return "fedora"
if shutil.which("pacman"):
return "arch"
return "unknown"
# ── Python / pip check ─────────────────────────────────────────────────────────
def check_python():
section("Checking Python")
major, minor = sys.version_info[:2]
print(f" Python {major}.{minor} detected")
if major < 3 or (major == 3 and minor < 8):
fail("Python 3.8+ is required. Please upgrade and re-run this script.")
ok("Python version is compatible")
def ensure_pip():
section("Checking pip")
try:
import pip # noqa: F401
ok("pip is available")
except ImportError:
info("pip not found — installing via ensurepip...")
run([sys.executable, "-m", "ensurepip", "--upgrade"])
ok("pip installed")
# Always upgrade pip to avoid resolver issues
run([sys.executable, "-m", "pip", "install", "--upgrade", "pip"])
ok("pip is up to date")
# ── yt-dlp ─────────────────────────────────────────────────────────────────────
def install_ytdlp():
section("Installing yt-dlp")
run([sys.executable, "-m", "pip", "install", "--upgrade", "yt-dlp"])
ok("yt-dlp installed/updated")
# ── ffmpeg ─────────────────────────────────────────────────────────────────────
def ffmpeg_already_installed() -> bool:
if shutil.which("ffmpeg"):
result = subprocess.run(
["ffmpeg", "-version"], capture_output=True, text=True, check=False
)
version_line = result.stdout.splitlines()[0] if result.stdout else "unknown"
info(f"ffmpeg already installed: {version_line}")
return True
return False
def install_ffmpeg_windows():
"""
On Windows, download the pre-built ffmpeg binary via winget or chocolatey.
Falls back to manual instructions if neither is available.
"""
if shutil.which("winget"):
info("Using winget to install ffmpeg...")
run(["winget", "install", "--id", "Gyan.FFmpeg", "-e", "--silent"])
elif shutil.which("choco"):
info("Using Chocolatey to install ffmpeg...")
run(["choco", "install", "ffmpeg", "-y"])
elif shutil.which("scoop"):
info("Using Scoop to install ffmpeg...")
run(["scoop", "install", "ffmpeg"])
else:
warn("No package manager found (winget / choco / scoop).")
print("""
Please install ffmpeg manually:
1. Go to https://www.gyan.dev/ffmpeg/builds/
2. Download the latest 'release essentials' zip
3. Extract it and add the 'bin' folder to your PATH
""")
return
ok("ffmpeg installed")
def install_ffmpeg_mac():
if shutil.which("brew"):
info("Using Homebrew to install ffmpeg...")
run(["brew", "install", "ffmpeg"])
elif shutil.which("port"):
info("Using MacPorts to install ffmpeg...")
run(["sudo", "port", "install", "ffmpeg"])
else:
warn("Homebrew not found. Installing Homebrew first...")
install_cmd = (
'/bin/bash -c "$(curl -fsSL '
'https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
)
subprocess.run(install_cmd, shell=True, check=True)
run(["brew", "install", "ffmpeg"])
ok("ffmpeg installed")
def install_ffmpeg_linux():
distro = linux_distro()
if distro == "debian":
info("Using apt-get (Debian/Ubuntu)...")
run(["sudo", "apt-get", "update", "-qq"])
run(["sudo", "apt-get", "install", "-y", "ffmpeg"])
elif distro == "fedora":
info("Using dnf (Fedora/RHEL)...")
# ffmpeg lives in RPM Fusion on Fedora
run(["sudo", "dnf", "install", "-y",
"https://download1.rpmfusion.org/free/fedora/"
"rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm"], check=False)
run(["sudo", "dnf", "install", "-y", "ffmpeg"])
elif distro == "arch":
info("Using pacman (Arch Linux)...")
run(["sudo", "pacman", "-Sy", "--noconfirm", "ffmpeg"])
else:
warn("Unrecognised Linux distro — cannot auto-install ffmpeg.")
print("""
Please install ffmpeg with your distro's package manager, e.g.:
sudo apt-get install ffmpeg # Debian / Ubuntu
sudo dnf install ffmpeg # Fedora
sudo pacman -S ffmpeg # Arch
""")
return
ok("ffmpeg installed")
def install_ffmpeg():
section("Installing ffmpeg")
if ffmpeg_already_installed():
ok("Skipping — ffmpeg is already installed")
return
if IS_WIN:
install_ffmpeg_windows()
elif IS_MAC:
install_ffmpeg_mac()
elif IS_LINUX:
install_ffmpeg_linux()
else:
warn(f"Unsupported OS: {OS}")
# ── Final verification ─────────────────────────────────────────────────────────
def verify():
section("Verification")
all_good = True
# yt-dlp
try:
import yt_dlp
ok(f"yt-dlp {yt_dlp.version.__version__}")
except ImportError:
fail("yt-dlp import failed after installation!")
all_good = False
# ffmpeg
if shutil.which("ffmpeg"):
result = subprocess.run(
["ffmpeg", "-version"], capture_output=True, text=True, check=False
)
version_line = result.stdout.splitlines()[0] if result.stdout else "unknown version"
ok(f"ffmpeg — {version_line}")
else:
warn("ffmpeg not found in PATH. High-quality merging may not work.")
warn("You can still download videos but 1080p/4K may be unavailable.")
all_good = False
return all_good
# ── Main ───────────────────────────────────────────────────────────────────────
def main():
print("\n" + "=" * 50)
print(" YouTube Downloader — Dependency Installer")
print("=" * 50)
print(f" OS : {OS} ({platform.machine()})")
print(f" Python : {sys.version.split()[0]}")
check_python()
ensure_pip()
install_ytdlp()
install_ffmpeg()
all_good = verify()
print("\n" + "=" * 50)
if all_good:
print(" 🎉 All dependencies installed successfully!")
print(" Run python yt_downloader.py to start downloading.")
else:
print(" ⚠️ Setup finished with warnings (see above).")
print("=" * 50 + "\n")
if __name__ == "__main__":
main()