diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..294cbf2 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,283 @@ +# ============================================================================= +# Warlock Studio — Gitea Actions CI/CD Pipeline +# ============================================================================= +name: Build and Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., 6.0.1)' + required: true + dry_run: + description: 'Dry run — build but do not create a release' + type: boolean + default: false + +env: + APP_NAME: Warlock-Studio + PYTHON_VERSION: '3.10' + PYTHON_WIN_URL: 'https://www.python.org/ftp/python/3.10.11/python-3.10.11-amd64.exe' + +jobs: + + # ========================================================================== + # VALIDATE — syntax + lint before building + # ========================================================================== + validate: + name: Validate source + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - name: Setup Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pyinstaller pyflakes + + - name: Syntax check + run: | + python -m pyflakes *.py + python -m compileall -q *.py + + - name: Verify .spec + run: | + python -c " + with open('Warlock-Studio.spec') as f: + c = f.read() + assert 'Analysis' in c + assert 'EXE' in c + print('OK .spec valid') + " + + # ========================================================================== + # BUILD — matrix: linux (native) + windows (cross via wine) + # ========================================================================== + build: + name: Build (${{ matrix.target }}) + needs: [validate] + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + target: [linux, windows] + + steps: + - uses: actions/checkout@v4 + + # ---- Common: Setup Python ---- + - name: Setup Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Install common system deps + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq libgl1-mesa-glx libegl1 libxkbcommon0 file + + - name: Install Python deps + run: | + python -m pip install --upgrade pip wheel setuptools + pip install -r requirements.txt + pip install pyinstaller + + # ---- Linux: native build ---- + - name: Build Linux native (PyInstaller) + if: matrix.target == 'linux' + run: pyinstaller Warlock-Studio.spec --noconfirm + + - name: Package Linux (tar.gz) + if: matrix.target == 'linux' + run: | + v="${{ github.ref_name }}" && v="${v#v}" + [ "${{ github.event_name }}" = "workflow_dispatch" ] && v="${{ github.event.inputs.version }}" + [ -z "$v" ] && v="dev" + a="${{ env.APP_NAME }}-${v}-linux-x64.tar.gz" + tar -czf "${a}" -C dist "${{ env.APP_NAME }}" + echo "ARCHIVE_NAME=${a}" >> $GITHUB_ENV + + - name: Verify Linux binary + if: matrix.target == 'linux' + run: | + ls -lh "dist/${{ env.APP_NAME }}/${{ env.APP_NAME }}" + file "dist/${{ env.APP_NAME }}/${{ env.APP_NAME }}" + + # ---- Windows: cross-build via Wine ---- + - name: Install Wine + Windows Python + if: matrix.target == 'windows' + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update -qq + sudo apt-get install -y -qq wine wine32 wine64 xvfb + + # Download Windows Python into stable location + mkdir -p /tmp/winbuild + wget -q "${{ env.PYTHON_WIN_URL }}" -O /tmp/winbuild/python-installer.exe + + - name: Setup Windows Python under Wine + if: matrix.target == 'windows' + run: | + export DISPLAY=:99 + Xvfb :99 -screen 0 1024x768x16 &>/dev/null & + sleep 1 + + # Install Python for Windows silently + wine /tmp/winbuild/python-installer.exe \ + /quiet InstallAllUsers=1 PrependPath=1 \ + Include_doc=0 Include_tcltk=1 \ + TargetDir='C:\Python310' 2>&1 | tail -5 + + # Verify + wine python --version 2>&1 + wine pip --version 2>&1 + + - name: Install Windows dependencies under Wine + if: matrix.target == 'windows' + run: | + # Map project directory as Windows drive + WINEPROJ="Z:$(pwd)" + # Install pip deps + wine pip install --no-input --no-cache-dir \ + -r "${WINEPROJ}/requirements.txt" 2>&1 | tail -5 + wine pip install --no-input --no-cache-dir \ + pyinstaller onnxruntime-directml 2>&1 | tail -5 + + - name: Build Windows binary (PyInstaller via Wine) + if: matrix.target == 'windows' + run: | + WINEPROJ="Z:$(pwd)" + wine pyinstaller "${WINEPROJ}/Warlock-Studio.spec" \ + --noconfirm --distpath "${WINEPROJ}/dist" 2>&1 | tail -10 + + - name: Verify Windows binary + if: matrix.target == 'windows' + run: | + ls -lh "dist/${{ env.APP_NAME }}/${{ env.APP_NAME }}.exe" + file "dist/${{ env.APP_NAME }}/${{ env.APP_NAME }}.exe" + + - name: Package Windows (ZIP) + if: matrix.target == 'windows' + run: | + v="${{ github.ref_name }}" && v="${v#v}" + [ "${{ github.event_name }}" = "workflow_dispatch" ] && v="${{ github.event.inputs.version }}" + [ -z "$v" ] && v="dev" + a="${{ env.APP_NAME }}-${v}-win64.zip" + cd dist + zip -r "${a}" "${{ env.APP_NAME }}" + cd .. + mv "dist/${a}" . + echo "ARCHIVE_NAME=${a}" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APP_NAME }}-${{ matrix.target }} + path: ${{ env.ARCHIVE_NAME }} + + # ========================================================================== + # RELEASE — create Gitea release + attach binaries + # ========================================================================== + release: + name: Create Release + needs: [build] + runs-on: ubuntu-22.04 + if: github.event_name != 'workflow_dispatch' || !github.event.inputs.dry_run + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/download-artifact@v4 + with: + pattern: ${{ env.APP_NAME }}-* + path: artifacts + merge-multiple: true + + - name: List artifacts + run: ls -lh artifacts/ + + - name: Determine version + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "tag=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + else + echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT + v="${{ github.ref_name }}" && echo "version=${v#v}" >> $GITHUB_OUTPUT + fi + + - name: Prepare release notes + run: | + if [ -f CHANGELOG.md ]; then + awk '/^## /{if(c) exit; c=1; next} c' CHANGELOG.md > release-notes.md 2>/dev/null || true + fi + [ -s release-notes.md ] || echo "Release ${{ steps.version.outputs.tag }}" > release-notes.md + + - name: Create Gitea Release + id: create_release + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} + run: | + BODY=$(cat release-notes.md | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))") + PAYLOAD='{ + "tag_name": "${{ steps.version.outputs.tag }}", + "target_commitish": "${{ github.sha }}", + "name": "Warlock Studio ${{ steps.version.outputs.version }}", + "body": '"${BODY}"', + "draft": false, + "prerelease": false + }' + + RESP=$(curl -s -X POST \ + -H "Authorization: token ${RELEASE_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "${PAYLOAD}" \ + "${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases") + + ID=$(echo "${RESP}" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null || echo "") + + if [ -z "${ID}" ]; then + echo "ERROR creating release:" + echo "${RESP}" + exit 1 + fi + + echo "release_id=${ID}" >> $GITHUB_OUTPUT + echo "Release ID: ${ID}" + + - name: Upload assets to release + env: + RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} + run: | + ID="${{ steps.create_release.outputs.release_id }}" + URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases/${ID}/assets" + + for a in artifacts/*; do + [ -f "${a}" ] || continue + fname=$(basename "${a}") + echo "Uploading: ${fname} ($(stat -c%s "${a}") bytes)" + + curl -s -X POST \ + -H "Authorization: token ${RELEASE_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@${a}" \ + "${URL}?name=${fname}" > /dev/null + + if [ $? -eq 0 ]; then + echo " OK" + else + echo " FAIL" + fi + done diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..17dea9e --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,103 @@ +# Maintainer: Warlock Studio +# Contributor: Ivan Ayub +# Arch Linux PKGBUILD — builds Warlock Studio from source using PyInstaller +# ============================================================================= +# This PKGBUILD is provided for reference / self-build. For AUR submission +# replace pkgver() with the actual release tag and uncomment source=() array. +# ============================================================================= + +pkgname=warlock-studio +pkgver=6.0 +pkgrel=1 +pkgdesc="AI-powered video upscaling, restoration, denoising and frame interpolation" +arch=('x86_64') +url="https://github.com/Ivan-Ayub97/Warlock-Studio" +license=('MIT') +depends=( + 'python' + 'python-pip' + 'python-customtkinter' + 'python-opencv' + 'python-numpy' + 'python-pillow' + 'python-moviepy' + 'python-natsort' + 'python-packaging' + 'python-psutil' + 'python-requests' + 'python-tkinterdnd2' + 'tk' + 'onnxruntime-opt' # or onnxruntime for CPU-only + 'ffmpeg' + 'libxkbcommon' + 'libxcb' + 'libgl' +) +makedepends=( + 'python-build' + 'python-installer' + 'python-wheel' + 'python-pyinstaller' +) +optdepends=( + 'python-onnxruntime-opt: GPU-accelerated ONNX inference (CUDA)' + 'python-onnxruntime-directml: DirectML backend for Windows (not applicable)' +) +conflicts=() +provides=("${pkgname}") +source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz") +sha256sums=('SKIP') +validpgpkeys=() + +build() { + cd "${srcdir}/${pkgname}-${pkgver}" + + # Install Python dependencies into temporary venv for PyInstaller + python -m venv --system-site-packages _buildenv + source _buildenv/bin/activate + + pip install --no-input --no-cache-dir -r requirements.txt + pip install --no-input --no-cache-dir pyinstaller + + # Build with PyInstaller + pyinstaller Warlock-Studio.spec --noconfirm + + deactivate + rm -rf _buildenv +} + +package() { + cd "${srcdir}/${pkgname}-${pkgver}" + + # Install into /opt/warlock-studio + install -dm755 "${pkgdir}/opt/warlock-studio" + cp -r dist/Warlock-Studio/* "${pkgdir}/opt/warlock-studio/" + + # Desktop entry + install -dm755 "${pkgdir}/usr/share/applications" + cat > "${pkgdir}/usr/share/applications/warlock-studio.desktop" << EOF +[Desktop Entry] +Name=Warlock Studio +Comment=AI-powered video upscaling, restoration and frame interpolation +Exec=/opt/warlock-studio/Warlock-Studio +Icon=warlock-studio +Terminal=false +Type=Application +Categories=Graphics;Video;AudioVideo; +StartupWMClass=Warlock-Studio +EOF + + # Icon + install -dm755 "${pkgdir}/usr/share/icons/hicolor/256x256/apps" + install -m644 logo.ico "${pkgdir}/usr/share/icons/hicolor/256x256/apps/warlock-studio.ico" 2>/dev/null || true + + # Symlink to PATH + install -dm755 "${pkgdir}/usr/bin" + ln -sf "/opt/warlock-studio/Warlock-Studio" "${pkgdir}/usr/bin/warlock-studio" + + # License + install -dm755 "${pkgdir}/usr/share/licenses/${pkgname}" + install -m644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/" 2>/dev/null || true +} + +# vim:set ts=2 sw=2 et: diff --git a/build-scripts/build-linux-portable.sh b/build-scripts/build-linux-portable.sh new file mode 100755 index 0000000..f8078be --- /dev/null +++ b/build-scripts/build-linux-portable.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash +# ============================================================================= +# Warlock Studio — Linux Portable Build Script +# ============================================================================= +# Builds a portable AppDir/AppImage or tar.gz of the PyInstaller output. +# +# Usage: +# ./build-scripts/build-linux-portable.sh [--appimage] [--output-dir=./dist] +# +# Requires: python3, pip, pyinstaller, (optional: appimagetool for --appimage) +# ============================================================================= +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_DIR" + +APP_NAME="Warlock-Studio" +BUILD_DIR="dist" +OUTPUT_DIR="${PROJECT_DIR}/${BUILD_DIR}" + +# ---- Parse arguments ---- +BUILD_APPIMAGE=false +while [[ $# -gt 0 ]]; do + case "$1" in + --appimage) BUILD_APPIMAGE=true; shift ;; + --output-dir=*) OUTPUT_DIR="${1#*=}"; shift ;; + --output-dir) OUTPUT_DIR="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +echo "==========================================" +echo " Warlock Studio — Linux Build" +echo "==========================================" + +# ---- Step 1: Install system dependencies ---- +echo "[1/5] Checking system dependencies..." +for cmd in python3 pip3; do + if ! command -v "$cmd" &>/dev/null; then + echo "ERROR: $cmd not found. Install python3 and pip." + exit 1 + fi +done + +# ---- Step 2: Install Python dependencies ---- +echo "[2/5] Installing Python dependencies..." +pip3 install --upgrade pip wheel setuptools +pip3 install -r "${PROJECT_DIR}/requirements.txt" +pip3 install pyinstaller + +# ---- Step 3: Build with PyInstaller ---- +echo "[3/5] Building with PyInstaller..." +pyinstaller "${PROJECT_DIR}/Warlock-Studio.spec" --noconfirm --distpath "${OUTPUT_DIR}" + +# Verify the binary was created +if [ -f "${OUTPUT_DIR}/${APP_NAME}/${APP_NAME}" ]; then + echo " Binary: ${OUTPUT_DIR}/${APP_NAME}/${APP_NAME}" + file "${OUTPUT_DIR}/${APP_NAME}/${APP_NAME}" +elif [ -f "${OUTPUT_DIR}/${APP_NAME}/${APP_NAME}.exe" ]; then + echo " Binary: ${OUTPUT_DIR}/${APP_NAME}/${APP_NAME}.exe" +else + echo "ERROR: Build output not found at ${OUTPUT_DIR}/${APP_NAME}/" + ls -la "${OUTPUT_DIR}/${APP_NAME}" 2>/dev/null || echo " (directory missing)" + exit 1 +fi + +# ---- Step 4: Create portable tar.gz ---- +echo "[4/5] Creating portable tar.gz..." +VERSION="" +if [ -n "${CI_COMMIT_TAG:-}" ]; then + VERSION="${CI_COMMIT_TAG#v}" +elif command -v git &>/dev/null; then + VERSION="$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")" + VERSION="${VERSION#v}" +fi +[ -z "$VERSION" ] && VERSION="dev" + +ARCHIVE_NAME="${APP_NAME}-${VERSION}-linux-x64.tar.gz" +tar -czf "${ARCHIVE_NAME}" -C "${OUTPUT_DIR}" "${APP_NAME}" +echo " Archive: ${ARCHIVE_NAME} ($(du -h "${ARCHIVE_NAME}" | cut -f1))" + +# ---- Step 5: Optionally build AppImage ---- +if [ "$BUILD_APPIMAGE" = true ]; then + echo "[5/5] Creating AppImage..." + if ! command -v appimagetool &>/dev/null && [ ! -f "appimagetool" ]; then + echo " Downloading appimagetool..." + wget -q "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O appimagetool + chmod +x appimagetool + fi + APPIMAGETOOL=$(command -v appimagetool || echo "./appimagetool") + + # Create AppDir structure + APPDIR="${OUTPUT_DIR}/${APP_NAME}.AppDir" + mkdir -p "${APPDIR}/usr/bin" + cp -r "${OUTPUT_DIR}/${APP_NAME}"/* "${APPDIR}/usr/bin/" + + # Create desktop entry + cat > "${APPDIR}/${APP_NAME}.desktop" << EOF +[Desktop Entry] +Name=Warlock Studio +Comment=AI-powered video upscaling, restoration and frame interpolation +Exec=${APP_NAME} +Icon=${APP_NAME} +Terminal=false +Type=Application +Categories=Graphics;Video; +EOF + + # Copy icon + cp "${PROJECT_DIR}/logo.ico" "${APPDIR}/${APP_NAME}.png" 2>/dev/null || true + + # Create AppRun + cat > "${APPDIR}/AppRun" << 'APPRUN_EOF' +#!/usr/bin/env bash +HERE="$(dirname "$(readlink -f "$0")")" +export PATH="${HERE}/usr/bin:${PATH}" +export LD_LIBRARY_PATH="${HERE}/usr/bin/_internal:${LD_LIBRARY_PATH}" +exec "${HERE}/usr/bin/Warlock-Studio" "$@" +APPRUN_EOF + chmod +x "${APPDIR}/AppRun" + + # Build AppImage + ARCH=x86_64 "$APPIMAGETOOL" "${APPDIR}" "${APP_NAME}-${VERSION}-x86_64.AppImage" + echo " AppImage: ${APP_NAME}-${VERSION}-x86_64.AppImage" +fi + +echo "" +echo "==========================================" +echo " BUILD COMPLETE" +echo "==========================================" +echo "Output: ${ARCHIVE_NAME}" +[ "$BUILD_APPIMAGE" = true ] && echo "AppImage: ${APP_NAME}-${VERSION}-x86_64.AppImage" diff --git a/build-scripts/build-windows.ps1 b/build-scripts/build-windows.ps1 new file mode 100644 index 0000000..c09d4e4 --- /dev/null +++ b/build-scripts/build-windows.ps1 @@ -0,0 +1,102 @@ +# ============================================================================= +# Warlock Studio — Windows Build Script (PowerShell) +# ============================================================================= +# Builds with PyInstaller and optionally packages into an installer via Inno Setup. +# +# Usage: +# .\build-scripts\build-windows.ps1 [-InnoSetup] [-OutputDir .\dist] +# +# Requires: Python 3.10+, pip, PyInstaller +# Optional: Inno Setup (for -InnoSetup flag) +# ============================================================================= +param( + [switch]$InnoSetup, + [string]$OutputDir = (Join-Path (Get-Location) "dist") +) + +$ErrorActionPreference = "Stop" +$ProjectRoot = Split-Path -Parent (Split-Path -Parent $PSCommandPath) +$AppName = "Warlock-Studio" + +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " Warlock Studio — Windows Build" -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan + +# ---- Step 1: Install Python dependencies ---- +Write-Host "[1/5] Installing Python dependencies..." -ForegroundColor Yellow +python -m pip install --upgrade pip wheel setuptools +pip install -r (Join-Path $ProjectRoot "requirements.txt") +pip install pyinstaller onnxruntime-directml + +# ---- Step 2: Build with PyInstaller ---- +Write-Host "[2/5] Building with PyInstaller..." -ForegroundColor Yellow +$specFile = Join-Path $ProjectRoot "Warlock-Studio.spec" +$distPath = $OutputDir +pyinstaller $specFile --noconfirm --distpath $distPath + +# Verify output +$binaryPath = Join-Path $distPath $AppName "$AppName.exe" +if (-not (Test-Path $binaryPath)) { + Write-Error "Build failed: $binaryPath not found" + exit 1 +} +Write-Host " Binary: $binaryPath" -ForegroundColor Green + +# ---- Step 3: Create versioned archive ---- +Write-Host "[3/5] Creating ZIP archive..." -ForegroundColor Yellow +$version = "dev" +$tag = git describe --tags --abbrev=0 2>$null +if ($tag) { $version = $tag.TrimStart('v') } + +$archiveName = "$AppName-$version-win64.zip" +$archivePath = Join-Path $ProjectRoot $archiveName +$buildDir = Join-Path $distPath $AppName +Compress-Archive -Path "$buildDir\*" -DestinationPath $archivePath -Force +Write-Host " Archive: $archivePath" -ForegroundColor Green + +# ---- Step 4: Build Inno Setup installer (optional) ---- +if ($InnoSetup) { + Write-Host "[4/5] Building Inno Setup installer..." -ForegroundColor Yellow + + # Check if ISCC is available + $iscc = Get-Command "iscc" -ErrorAction SilentlyContinue + if (-not $iscc) { + $possiblePaths = @( + "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe", + "${env:ProgramFiles}\Inno Setup 6\ISCC.exe", + "${env:ProgramFiles(x86)}\Inno Setup 5\ISCC.exe" + ) + $isccPath = $possiblePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 + if (-not $isccPath) { + Write-Warning "Inno Setup not found. Skipping installer build." + Write-Warning " Install from: https://jrsoftware.org/isdl.php" + } else { + $iscc = $isccPath + } + } + + if ($iscc) { + $issFile = Join-Path $ProjectRoot "Setup.iss" + if (Test-Path $issFile) { + & $iscc $issFile + Write-Host " Installer built." -ForegroundColor Green + } else { + Write-Warning "Setup.iss not found. Skipping installer." + } + } +} else { + Write-Host "[4/5] Skipped (use -InnoSetup to build installer)" -ForegroundColor Gray +} + +# ---- Step 5: Cleanup ---- +Write-Host "[5/5] Cleanup..." -ForegroundColor Yellow +Remove-Item -Recurse -Force "build" -ErrorAction SilentlyContinue + +Write-Host "" +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host " BUILD COMPLETE" -ForegroundColor Cyan +Write-Host "==========================================" -ForegroundColor Cyan +Write-Host "Output: $archiveName" -ForegroundColor Green +if ($InnoSetup -and $iscc) { + Write-Host "Installer: Output\Warlock-Studio-$version-Full-Installer.exe" -ForegroundColor Green +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0890741 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,83 @@ +# ============================================================================= +# Warlock Studio — Python Dependencies +# ============================================================================= +# Platform: Python 3.10+ +# Framework: CustomTkinter GUI, OpenCV + ONNX Runtime for AI media processing +# ============================================================================= + +# --------------------------------------------------------------------------- +# SECTION 1 — Core Runtime Dependencies +# --------------------------------------------------------------------------- + +# GUI framework — modern, themed tkinter widgets +customtkinter>=5.2.2 + +# OpenCV — image/video I/O, color conversion, resizing, frame manipulation +opencv-python>=4.8.1.78 + +# NumPy — multidimensional array backend for OpenCV, ONNX, and image ops +numpy>=1.24.0 + +# ONNX Runtime — AI model inference (upscaling, restoration, frame interpolation) +onnxruntime>=1.16.0 + +# Pillow — PILLow Image loading for GUI thumbnails and splash screen +Pillow>=10.2.0 + +# MoviePy — video clip assembly from processed image sequences +moviepy>=1.0.3 + +# --------------------------------------------------------------------------- +# SECTION 2 — Utility Dependencies +# --------------------------------------------------------------------------- + +# natsort — natural (human-friendly) sorting of file names +natsort>=8.4.0 + +# packaging — PEP 440 version comparison for update checks +packaging>=23.2 + +# psutil — system resource monitoring (RAM, CPU) for adaptive processing +psutil>=5.9.8 + +# requests — HTTP client for update checks and online features +requests>=2.31.0 + +# tkinterdnd2 — drag-and-drop support for the GUI +tkinterdnd2>=0.3.0 + +# --------------------------------------------------------------------------- +# SECTION 3 — Optional / Platform-Specific Backends +# --------------------------------------------------------------------------- + +# OpenCV headless (no GUI) — use instead of opencv-python on Linux servers +# or headless environments where no display is available. +# pip install opencv-python-headless +# opencv-python-headless>=4.8.1.78 + +# ONNX Runtime with DirectML — Windows-only, enables GPU inference via +# DirectML for AMD, Intel, and NVIDIA GPUs without CUDA. +# pip install onnxruntime-directml +# onnxruntime-directml>=1.16.0 + +# ONNX Runtime with CUDA — NVIDIA GPU acceleration via CUDA 11.x/12.x. +# Requires matching CUDA runtime and cuDNN installed on the system. +# pip install onnxruntime-gpu +# onnxruntime-gpu>=1.16.0 + +# wmi — Windows Management Instrumentation (GPU info on Windows). +# Optional; only used if available. +# wmi>=1.5.1 + +# GPUtil — NVIDIA GPU information (Linux/Windows). +# Optional; only used if available. +# GPUtil>=1.4.0 + +# --------------------------------------------------------------------------- +# SECTION 4 — Build / Packaging +# --------------------------------------------------------------------------- + +# PyInstaller — bundle the application into a standalone executable. +# Install separately from runtime deps (build step only). +# pip install pyinstaller +# pyinstaller>=6.3.0