mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
167 lines
6.1 KiB
Python
167 lines
6.1 KiB
Python
import os
|
|
import shutil
|
|
import tarfile
|
|
import zipfile
|
|
import urllib.request
|
|
import ssl
|
|
import platform
|
|
import subprocess
|
|
|
|
# Ignore SSL certificate errors
|
|
ssl._create_default_https_context = ssl._create_unverified_context
|
|
|
|
# Constants
|
|
THIRD_PARTY_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "3rd")
|
|
FFMPEG_DIR = os.path.join(THIRD_PARTY_DIR, "ffmpeg6")
|
|
TEMP_DIR = os.path.join(THIRD_PARTY_DIR, "temp_ffmpeg_download")
|
|
|
|
# Versions and URLs
|
|
# Using BtbN for consistency on Linux/Windows
|
|
LINUX_AMD64_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n6.1-latest-linux64-gpl-shared-6.1.tar.xz"
|
|
LINUX_ARM64_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n6.1-latest-linuxarm64-gpl-shared-6.1.tar.xz"
|
|
WINDOWS_AMD64_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n6.1-latest-win64-gpl-shared-6.1.zip"
|
|
|
|
def log(msg):
|
|
print(f"[FFmpeg Setup] {msg}")
|
|
|
|
def download_file(url, dest_path):
|
|
log(f"Downloading {url}...")
|
|
try:
|
|
urllib.request.urlretrieve(url, dest_path)
|
|
return True
|
|
except Exception as e:
|
|
log(f"Error downloading {url}: {e}")
|
|
return False
|
|
|
|
def extract_archive(path, extract_to):
|
|
log(f"Extracting {path}...")
|
|
try:
|
|
if path.endswith('.tar.xz'):
|
|
with tarfile.open(path, "r:xz") as tar:
|
|
tar.extractall(path=extract_to)
|
|
elif path.endswith('.zip'):
|
|
with zipfile.ZipFile(path, 'r') as zip_ref:
|
|
zip_ref.extractall(extract_to)
|
|
return True
|
|
except Exception as e:
|
|
log(f"Error extracting {path}: {e}")
|
|
return False
|
|
|
|
def setup_linux():
|
|
log("Setting up Linux libraries...")
|
|
linux_dir = os.path.join(FFMPEG_DIR, "linux")
|
|
if os.path.exists(linux_dir):
|
|
shutil.rmtree(linux_dir)
|
|
|
|
# Create structure
|
|
os.makedirs(os.path.join(linux_dir, "lib", "amd64"))
|
|
os.makedirs(os.path.join(linux_dir, "lib", "arm64"))
|
|
os.makedirs(os.path.join(linux_dir, "include"))
|
|
|
|
# Process AMD64
|
|
f_amd64 = os.path.join(TEMP_DIR, "linux_amd64.tar.xz")
|
|
if download_file(LINUX_AMD64_URL, f_amd64) and extract_archive(f_amd64, TEMP_DIR):
|
|
extracted_root = [d for d in os.listdir(TEMP_DIR) if d.startswith("ffmpeg-n") and "linux64" in d][0]
|
|
src = os.path.join(TEMP_DIR, extracted_root)
|
|
|
|
# Copy includes (use AMD64 version as the canonical include for Linux)
|
|
shutil.copytree(os.path.join(src, "include"), os.path.join(linux_dir, "include"), dirs_exist_ok=True)
|
|
|
|
# Copy libs
|
|
src_lib = os.path.join(src, "lib")
|
|
dst_lib = os.path.join(linux_dir, "lib", "amd64")
|
|
shutil.copytree(src_lib, dst_lib, dirs_exist_ok=True)
|
|
|
|
# Process ARM64
|
|
f_arm64 = os.path.join(TEMP_DIR, "linux_arm64.tar.xz")
|
|
if download_file(LINUX_ARM64_URL, f_arm64) and extract_archive(f_arm64, TEMP_DIR):
|
|
extracted_root = [d for d in os.listdir(TEMP_DIR) if d.startswith("ffmpeg-n") and "linuxarm64" in d][0]
|
|
src = os.path.join(TEMP_DIR, extracted_root)
|
|
|
|
# Copy libs
|
|
src_lib = os.path.join(src, "lib")
|
|
dst_lib = os.path.join(linux_dir, "lib", "arm64")
|
|
shutil.copytree(src_lib, dst_lib, dirs_exist_ok=True)
|
|
|
|
def setup_windows():
|
|
log("Setting up Windows libraries...")
|
|
win_dir = os.path.join(FFMPEG_DIR, "windows")
|
|
if os.path.exists(win_dir):
|
|
shutil.rmtree(win_dir)
|
|
|
|
f_win = os.path.join(TEMP_DIR, "win_amd64.zip")
|
|
if download_file(WINDOWS_AMD64_URL, f_win) and extract_archive(f_win, TEMP_DIR):
|
|
extracted_root = [d for d in os.listdir(TEMP_DIR) if d.startswith("ffmpeg-n") and "win64" in d][0]
|
|
src = os.path.join(TEMP_DIR, extracted_root)
|
|
|
|
# Copy includes and libs
|
|
shutil.copytree(os.path.join(src, "include"), os.path.join(win_dir, "include"))
|
|
shutil.copytree(os.path.join(src, "lib"), os.path.join(win_dir, "lib"))
|
|
# Also copy bin (dlls) to lib for convenience if needed, or keep separate
|
|
shutil.copytree(os.path.join(src, "bin"), os.path.join(win_dir, "bin"))
|
|
|
|
def setup_mac():
|
|
log("Setting up macOS libraries (via Brew)...")
|
|
mac_dir = os.path.join(FFMPEG_DIR, "mac")
|
|
if os.path.exists(mac_dir):
|
|
shutil.rmtree(mac_dir)
|
|
|
|
try:
|
|
# Get brew prefix
|
|
result = subprocess.run(["brew", "--prefix", "ffmpeg"], capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
log("FFmpeg not found via brew. Please install: brew install ffmpeg")
|
|
return
|
|
|
|
brew_ffmpeg_path = result.stdout.strip()
|
|
log(f"Found brew ffmpeg at {brew_ffmpeg_path}")
|
|
|
|
# Create symlink or copy. Copy is safer for portability if we move the folder,
|
|
# but symlink is better for updates.
|
|
# Given "3rd" implies vendoring, let's symlink to keep it lightweight
|
|
# but pointing to the valid system install.
|
|
# Wait, if we symlink 'mac' -> '/opt/homebrew/opt/ffmpeg',
|
|
# then 'mac/include' and 'mac/lib' exist automatically.
|
|
|
|
os.symlink(brew_ffmpeg_path, mac_dir)
|
|
log(f"Symlinked {mac_dir} -> {brew_ffmpeg_path}")
|
|
|
|
except Exception as e:
|
|
log(f"Error setting up Mac: {e}")
|
|
|
|
def main():
|
|
if not os.path.exists(THIRD_PARTY_DIR):
|
|
os.makedirs(THIRD_PARTY_DIR)
|
|
|
|
if not os.path.exists(FFMPEG_DIR):
|
|
os.makedirs(FFMPEG_DIR)
|
|
|
|
if os.path.exists(TEMP_DIR):
|
|
shutil.rmtree(TEMP_DIR)
|
|
os.makedirs(TEMP_DIR)
|
|
|
|
# Always setup Linux (for cross compilation)
|
|
setup_linux()
|
|
|
|
# If on Windows, setup Windows
|
|
if platform.system() == "Windows":
|
|
setup_windows()
|
|
|
|
# If on Mac, setup Mac
|
|
if platform.system() == "Darwin":
|
|
setup_mac()
|
|
|
|
# Optional: If user wants to setup Windows on Mac (for cross compile), we could enabled it.
|
|
# For now, let's just enable Windows download if explicitly asked or simple logic.
|
|
# Let's just download Windows anyway so the folder is complete?
|
|
# It's about 30MB.
|
|
if platform.system() != "Windows":
|
|
setup_windows()
|
|
|
|
# Cleanup
|
|
shutil.rmtree(TEMP_DIR)
|
|
log("Done.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|