diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml deleted file mode 100644 index 10e012f..0000000 --- a/.gitea/workflows/build.yml +++ /dev/null @@ -1,141 +0,0 @@ -name: Build and Push Docker Image - -on: - push: - branches: - - main - - develop - tags: - - 'v*.*.*' - pull_request: - branches: - - main - workflow_dispatch: - inputs: - tag: - description: 'Custom tag for the image' - required: false - default: 'manual' - -env: - REGISTRY: dev.pivoine.art - IMAGE_NAME: valknar/realesrgan-api - -jobs: - build-gpu: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - platforms: linux/amd64 - - - name: Log in to Gitea Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ gitea.actor }} - password: ${{ secrets.REGISTRY_TOKEN }} - - - name: Extract metadata (GPU) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=branch - type=ref,event=pr - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha,prefix={{branch}}- - type=raw,value=${{ gitea.event.inputs.tag }},enable=${{ gitea.event_name == 'workflow_dispatch' }} - labels: | - org.opencontainers.image.title=realesrgan-api - org.opencontainers.image.description=REST API for Real-ESRGAN image upscaling (GPU) - org.opencontainers.image.vendor=valknar - - - name: Build and push GPU image - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64 - push: ${{ gitea.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: VARIANT=gpu - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-gpu - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-gpu,mode=max - - - name: Summary - if: gitea.event_name != 'pull_request' - run: | - echo "### GPU Image Published" >> $GITEA_STEP_SUMMARY - echo "**Tags:**" >> $GITEA_STEP_SUMMARY - echo "\`\`\`" >> $GITEA_STEP_SUMMARY - echo "${{ steps.meta.outputs.tags }}" >> $GITEA_STEP_SUMMARY - echo "\`\`\`" >> $GITEA_STEP_SUMMARY - - build-cpu: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - platforms: linux/amd64 - - - name: Log in to Gitea Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ gitea.actor }} - password: ${{ secrets.REGISTRY_TOKEN }} - - - name: Extract metadata (CPU) - id: meta-cpu - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - flavor: suffix=-cpu - tags: | - type=raw,value=latest-cpu,enable={{is_default_branch}} - type=ref,event=branch,suffix=-cpu - type=ref,event=pr,suffix=-cpu - type=semver,pattern={{version}},suffix=-cpu - type=sha,prefix={{branch}}-,suffix=-cpu - labels: | - org.opencontainers.image.title=realesrgan-api - org.opencontainers.image.description=REST API for Real-ESRGAN image upscaling (CPU) - org.opencontainers.image.vendor=valknar - - - name: Build and push CPU image - uses: docker/build-push-action@v5 - with: - context: . - platforms: linux/amd64 - push: ${{ gitea.event_name != 'pull_request' }} - tags: ${{ steps.meta-cpu.outputs.tags }} - labels: ${{ steps.meta-cpu.outputs.labels }} - build-args: VARIANT=cpu - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-cpu - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-cpu,mode=max - - - name: Summary - if: gitea.event_name != 'pull_request' - run: | - echo "### CPU Image Published" >> $GITEA_STEP_SUMMARY - echo "**Tags:**" >> $GITEA_STEP_SUMMARY - echo "\`\`\`" >> $GITEA_STEP_SUMMARY - echo "${{ steps.meta-cpu.outputs.tags }}" >> $GITEA_STEP_SUMMARY - echo "\`\`\`" >> $GITEA_STEP_SUMMARY diff --git a/.gitea/workflows/docker-build-push.yml b/.gitea/workflows/docker-build-push.yml new file mode 100644 index 0000000..ef6208c --- /dev/null +++ b/.gitea/workflows/docker-build-push.yml @@ -0,0 +1,82 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + - develop + tags: + - 'v*.*.*' + pull_request: + branches: + - main + workflow_dispatch: + inputs: + tag: + description: 'Custom tag for the image' + required: false + default: 'manual' + +env: + REGISTRY: dev.pivoine.art + IMAGE_NAME: valknar/realesrgan-api + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/amd64 + + - name: Log in to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,prefix={{branch}}- + type=raw,value=${{ gitea.event.inputs.tag }},enable=${{ gitea.event_name == 'workflow_dispatch' }} + labels: | + org.opencontainers.image.title=realesrgan-api + org.opencontainers.image.description=REST API for Real-ESRGAN image upscaling + org.opencontainers.image.vendor=valknar + + - name: Build and push image + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64 + push: ${{ gitea.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max + + - name: Summary + if: gitea.event_name != 'pull_request' + run: | + echo "### Image Published" >> $GITEA_STEP_SUMMARY + echo "**Tags:**" >> $GITEA_STEP_SUMMARY + echo "\`\`\`" >> $GITEA_STEP_SUMMARY + echo "${{ steps.meta.outputs.tags }}" >> $GITEA_STEP_SUMMARY + echo "\`\`\`" >> $GITEA_STEP_SUMMARY diff --git a/API_USAGE.md b/API_USAGE.md index b8929e1..2772035 100644 --- a/API_USAGE.md +++ b/API_USAGE.md @@ -405,10 +405,7 @@ Detailed system information and resource usage. "cpu_usage_percent": 25.3, "memory_usage_percent": 42.1, "disk_usage_percent": 15.2, - "gpu_available": true, - "gpu_memory_mb": 8192, - "gpu_memory_used_mb": 2048, - "execution_providers": ["cuda"], + "execution_providers": ["cpu"], "models_dir_size_mb": 268.4, "jobs_queue_length": 3 } diff --git a/CLAUDE.md b/CLAUDE.md index 08729a6..4ac1a33 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code when working with this repository. ## Overview -This is the Real-ESRGAN API project - a sophisticated, full-featured REST API for image upscaling using Real-ESRGAN. The API supports both synchronous and asynchronous (job-based) processing with Docker containerization for CPU and GPU deployments. +This is the Real-ESRGAN API project - a sophisticated, full-featured REST API for image upscaling using Real-ESRGAN. The API supports both synchronous and asynchronous (job-based) processing with Docker containerization for CPU deployments. ## Architecture @@ -32,11 +32,11 @@ This is the Real-ESRGAN API project - a sophisticated, full-featured REST API fo ## Development Workflow -### Local Setup (CPU) +### Local Setup ```bash # Install dependencies -pip install -r requirements.txt -r requirements-cpu.txt +pip install -r requirements.txt # Run development server python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 @@ -49,7 +49,7 @@ python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ### Docker Development ```bash -# Build CPU image +# Build image docker compose build # Run container @@ -62,19 +62,6 @@ docker compose logs -f api docker compose down ``` -### GPU Development - -```bash -# Build GPU image -docker compose -f docker-compose.gpu.yml build - -# Run with GPU -docker compose -f docker-compose.gpu.yml up -d - -# Check GPU usage -docker compose -f docker-compose.gpu.yml exec api nvidia-smi -``` - ## Configuration ### Environment Variables (prefix: RSR_) @@ -85,7 +72,7 @@ All settings from `app/config.py` can be configured via environment: RSR_UPLOAD_DIR=/data/uploads RSR_OUTPUT_DIR=/data/outputs RSR_MODELS_DIR=/data/models -RSR_EXECUTION_PROVIDERS=["cpu"] # or ["cuda"] for GPU +RSR_EXECUTION_PROVIDERS=["cpu"] RSR_TILE_SIZE=400 # Tile size for large images RSR_MAX_UPLOAD_SIZE_MB=500 RSR_SYNC_TIMEOUT_SECONDS=300 @@ -93,7 +80,7 @@ RSR_SYNC_TIMEOUT_SECONDS=300 ### Docker Compose Environment -Set in `docker-compose.yml` or `docker-compose.gpu.yml` `environment` section. +Set in `docker-compose.yml` `environment` section. ## API Endpoints @@ -152,7 +139,7 @@ This project follows similar patterns to facefusion-api: - **File Management**: Same `file_manager.py` utilities - **Worker Queue**: Similar async job processing architecture -- **Docker Setup**: Multi-variant CPU/GPU builds +- **Docker Setup**: CPU-only builds - **Configuration**: Environment-based settings with pydantic - **Gitea CI/CD**: Automatic Docker image building - **API Structure**: Organized routers and services @@ -199,16 +186,6 @@ curl -X POST http://localhost:8000/api/v1/models/download \ -d '{"models": ["RealESRGAN_x4plus"]}' ``` -### GPU Not Detected - -```bash -# Check GPU availability -docker compose -f docker-compose.gpu.yml exec api python -c "import torch; print(torch.cuda.is_available())" - -# Check system GPU -nvidia-smi -``` - ### Permission Issues with Volumes ```bash @@ -231,14 +208,13 @@ git push gitea main ``` Gitea workflows automatically: -- Build Docker images (CPU and GPU) +- Build Docker image - Run tests - Publish to Container Registry ## Important Notes - **Model Weights**: Downloaded from GitHub releases (~100MB each) -- **GPU Support**: Requires NVIDIA Docker runtime - **Async Processing**: Uses thread pool (configurable workers) - **Tile Processing**: Handles large images by splitting into tiles - **Data Persistence**: Volumes recommended for production diff --git a/Dockerfile b/Dockerfile index d062bff..dd2ac11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,42 +1,18 @@ -ARG VARIANT=cpu - -# ---- CPU base ---- -FROM python:3.11-slim AS base-cpu +# ---- Base Stage ---- +FROM python:3.11-slim AS base +# Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ curl libgl1 libglib2.0-0 \ && rm -rf /var/lib/apt/lists/* +# Install Python dependencies COPY requirements.txt /tmp/requirements.txt -COPY requirements-cpu.txt /tmp/requirements-cpu.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt -r /tmp/requirements-cpu.txt \ +RUN pip install --no-cache-dir -r /tmp/requirements.txt \ && rm /tmp/requirements*.txt -# ---- GPU base (CUDA 12.4) ---- -FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04 AS base-gpu - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - software-properties-common \ - && add-apt-repository ppa:deadsnakes/ppa \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - python3.11 python3.11-venv python3.11-dev \ - curl libgl1 libglib2.0-0 \ - && ln -sf /usr/bin/python3.11 /usr/bin/python3 \ - && ln -sf /usr/bin/python3 /usr/bin/python \ - && python3 -m ensurepip --upgrade \ - && python3 -m pip install --no-cache-dir --upgrade pip \ - && rm -rf /var/lib/apt/lists/* - -COPY requirements.txt /tmp/requirements.txt -COPY requirements-gpu.txt /tmp/requirements-gpu.txt -RUN pip install --no-cache-dir -r /tmp/requirements.txt -r /tmp/requirements-gpu.txt \ - && rm /tmp/requirements*.txt - -# ---- Final stage ---- -FROM base-${VARIANT} AS final +# ---- Final Stage ---- +FROM base AS final WORKDIR /app diff --git a/QUICKSTART.md b/QUICKSTART.md index e6fb435..3818e05 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,6 +1,6 @@ # Quick Start Guide -## 1. Local Development (CPU, ~2 minutes) +## 1. Local Development (~2 minutes) ```bash # Clone or navigate to project @@ -100,7 +100,7 @@ Try endpoints directly in Swagger UI! # Check system health curl http://localhost:8000/api/v1/health -# Get detailed system info (CPU, memory, GPU, etc.) +# Get detailed system info (CPU, memory, disk, etc.) curl http://localhost:8000/api/v1/system # Get API statistics @@ -110,25 +110,7 @@ curl http://localhost:8000/api/v1/stats curl http://localhost:8000/api/v1/jobs ``` -## 6. GPU Setup (Optional, requires NVIDIA) - -```bash -# Build with GPU support -docker compose -f docker-compose.gpu.yml build - -# Run with GPU -docker compose -f docker-compose.gpu.yml up -d - -# Verify GPU is accessible -docker compose -f docker-compose.gpu.yml exec api nvidia-smi - -# Download models again on GPU -curl -X POST http://localhost:8000/api/v1/models/download \ - -H 'Content-Type: application/json' \ - -d '{"models": ["RealESRGAN_x4plus"]}' -``` - -## 7. Production Deployment +## 6. Production Deployment ```bash # Update docker-compose.prod.yml with your registry/domain diff --git a/README.md b/README.md index 6509eb5..ad87efe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Real-ESRGAN API -REST API wrapping [Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN) for image upscaling. Features synchronous and asynchronous (job-based) processing with multi-target Docker builds (CPU + CUDA GPU support). +REST API wrapping [Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN) for image upscaling. Features synchronous and asynchronous (job-based) processing with Docker containerization. ## Features @@ -9,15 +9,15 @@ REST API wrapping [Real-ESRGAN](https://github.com/xinntao/Real-ESRGAN) for imag - **Multi-Model Support**: Multiple Real-ESRGAN models (2x, 3x, 4x upscaling) - **Batch Processing**: Process up to 100 images per batch request - **Model Management**: Download and manage upscaling models -- **Docker Deployment**: CPU and CUDA GPU support with multi-target builds +- **Docker Deployment**: Simplified containerized deployment - **Gitea CI/CD**: Automatic Docker image building and publishing - **API Documentation**: Interactive Swagger UI and ReDoc - **Health Checks**: Kubernetes-ready liveness and readiness probes -- **System Monitoring**: CPU, memory, disk, and GPU metrics +- **System Monitoring**: CPU, memory, and disk metrics ## Quick Start -### Local Development (CPU) +### Local Development ```bash # Build and run @@ -47,14 +47,6 @@ curl http://localhost:8000/api/v1/jobs/{job_id} curl http://localhost:8000/api/v1/jobs/{job_id}/result -o output.jpg ``` -### GPU Support - -```bash -# Build with GPU support and run -docker compose -f docker-compose.gpu.yml build -docker compose -f docker-compose.gpu.yml up -d -``` - ## API Endpoints ### Upscaling @@ -122,14 +114,14 @@ RSR_AUTO_CLEANUP_HOURS=24 # Auto cleanup interval ## Docker Deployment -### Development (CPU) +### Local/Development ```bash docker compose build docker compose up -d ``` -### Production (GPU) +### Production ```bash docker compose -f docker-compose.prod.yml up -d @@ -139,7 +131,7 @@ docker compose -f docker-compose.prod.yml up -d The `.gitea/workflows/build.yml` automatically: -1. Builds Docker images for CPU and GPU variants +1. Builds Docker image 2. Publishes to Gitea Container Registry 3. Tags with git commit SHA and latest @@ -174,7 +166,6 @@ app/ - **Synchronous Upscaling**: Best for small images (< 4MP) - **Asynchronous Jobs**: Recommended for large batches or high concurrency -- **GPU Performance**: 2-5x faster than CPU depending on model and image size - **Tile Processing**: Efficiently handles images up to 8K resolution ## Development @@ -182,7 +173,7 @@ app/ Install dependencies: ```bash -pip install -r requirements.txt -r requirements-cpu.txt +pip install -r requirements.txt ``` Run locally: diff --git a/app/routers/health.py b/app/routers/health.py index b88d2ed..c35c0e4 100644 --- a/app/routers/health.py +++ b/app/routers/health.py @@ -75,20 +75,6 @@ async def get_system_info() -> SystemInfo: disk = psutil.disk_usage('/') disk_percent = disk.percent - # GPU - gpu_available = False - gpu_memory_mb = None - gpu_memory_used_mb = None - - try: - import torch - gpu_available = torch.cuda.is_available() - if gpu_available: - gpu_memory_mb = int(torch.cuda.get_device_properties(0).total_memory / (1024 * 1024)) - gpu_memory_used_mb = int(torch.cuda.memory_allocated(0) / (1024 * 1024)) - except Exception: - pass - # Models directory size models_size = file_manager.get_directory_size_mb(settings.models_dir) @@ -103,9 +89,6 @@ async def get_system_info() -> SystemInfo: cpu_usage_percent=cpu_percent, memory_usage_percent=memory_percent, disk_usage_percent=disk_percent, - gpu_available=gpu_available, - gpu_memory_mb=gpu_memory_mb, - gpu_memory_used_mb=gpu_memory_used_mb, execution_providers=settings.get_execution_providers(), models_dir_size_mb=models_size, jobs_queue_length=queue_length, diff --git a/app/schemas/health.py b/app/schemas/health.py index d429410..79cb17a 100644 --- a/app/schemas/health.py +++ b/app/schemas/health.py @@ -20,9 +20,6 @@ class SystemInfo(BaseModel): cpu_usage_percent: float memory_usage_percent: float disk_usage_percent: float - gpu_available: bool - gpu_memory_mb: Optional[int] = None - gpu_memory_used_mb: Optional[int] = None execution_providers: list models_dir_size_mb: float jobs_queue_length: int diff --git a/app/services/realesrgan_bridge.py b/app/services/realesrgan_bridge.py index 1494c7b..0d5f742 100644 --- a/app/services/realesrgan_bridge.py +++ b/app/services/realesrgan_bridge.py @@ -83,7 +83,7 @@ class RealESRGANBridge: tile=settings.tile_size, tile_pad=settings.tile_pad, pre_pad=0, - half=('cuda' in settings.get_execution_providers()), + half=False, ) self.current_model = model_name @@ -134,7 +134,7 @@ class RealESRGANBridge: tile=settings.tile_size, tile_pad=settings.tile_pad, pre_pad=0, - half=('cuda' in settings.get_execution_providers()), + half=False, ) self.current_model = model_name @@ -198,15 +198,6 @@ class RealESRGANBridge: return self.upsampler.scale return 4 - def clear_memory(self) -> None: - """Clear GPU memory if available.""" - try: - import torch - torch.cuda.empty_cache() - logger.debug('GPU memory cleared') - except Exception: - pass - # Global instance _bridge: Optional[RealESRGANBridge] = None diff --git a/docker-compose.gpu.yml b/docker-compose.gpu.yml deleted file mode 100644 index 51ff916..0000000 --- a/docker-compose.gpu.yml +++ /dev/null @@ -1,27 +0,0 @@ -services: - api: - build: - context: . - args: - VARIANT: gpu - ports: - - "8000:8000" - volumes: - - ./data/uploads:/data/uploads - - ./data/outputs:/data/outputs - - ./data/models:/data/models - - ./data/temp:/data/temp - - ./data/jobs:/data/jobs - environment: - - RSR_EXECUTION_PROVIDERS=["cuda"] - - RSR_EXECUTION_THREAD_COUNT=8 - - RSR_TILE_SIZE=400 - - RSR_LOG_LEVEL=info - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] - restart: unless-stopped diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index bcc98c8..b88b4e2 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -10,17 +10,10 @@ services: - temp:/data/temp - jobs:/data/jobs environment: - - RSR_EXECUTION_PROVIDERS=["cuda"] + - RSR_EXECUTION_PROVIDERS=["cpu"] - RSR_EXECUTION_THREAD_COUNT=8 - RSR_TILE_SIZE=400 - RSR_LOG_LEVEL=info - deploy: - resources: - reservations: - devices: - - driver: nvidia - count: 1 - capabilities: [gpu] restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"] diff --git a/docker-compose.yml b/docker-compose.yml index f4a6e06..cf3d568 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,8 +2,6 @@ services: api: build: context: . - args: - VARIANT: cpu ports: - "8000:8000" volumes: diff --git a/requirements-cpu.txt b/requirements-cpu.txt deleted file mode 100644 index fb0d321..0000000 --- a/requirements-cpu.txt +++ /dev/null @@ -1,4 +0,0 @@ -torch==2.0.1 -torchvision==0.15.2 -realesrgan>=0.2.5 -basicsr>=1.4.1 diff --git a/requirements-gpu.txt b/requirements-gpu.txt deleted file mode 100644 index fbf8356..0000000 --- a/requirements-gpu.txt +++ /dev/null @@ -1,5 +0,0 @@ ---extra-index-url https://download.pytorch.org/whl/cu118 -torch==2.0.1 -torchvision==0.15.2 -realesrgan>=0.2.5 -basicsr>=1.4.1 diff --git a/requirements.txt b/requirements.txt index d5efc1f..49beb60 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,7 @@ opencv-python==4.8.1.78 numpy==1.24.3 scipy==1.11.4 tqdm==4.66.1 +torch==2.0.1 +torchvision==0.15.2 +realesrgan>=0.2.5 +basicsr>=1.4.1