- Fix CUDA version: 12.1 → 12.4.1 - Fix PyTorch version: 2.1.0 → 2.4.0 - Add resize_ratio parameter to API reference - Add parameter table with descriptions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
RunPod ProPainter Docker Image
Serverless GPU handler for video watermark removal using ProPainter AI inpainting.
Quick Start
Option A: Use Pre-built Public Image (Recommended)
A public image is available on GitHub Container Registry:
ghcr.io/conalmullan/video-toolkit-propainter:latest
Skip to Step 2: Deploy on RunPod below.
Option B: Build Your Own Image
cd docker/runpod-propainter
# Build for linux/amd64 (required for RunPod)
docker buildx build --platform linux/amd64 -t yourusername/video-toolkit-propainter:latest --push .
Build takes ~15-20 minutes (downloads ~2GB of model weights).
Deploy on RunPod
- Go to RunPod Serverless
- Click New Endpoint
- Configure:
- Docker Image:
ghcr.io/conalmullan/video-toolkit-propainter:latest - GPU: RTX 3090 or RTX 4090 (24GB VRAM recommended)
- Max Workers: 1 (scale up as needed)
- Idle Timeout: 5 seconds (fast scale-down)
- Execution Timeout: 3600 seconds (1 hour max)
- Docker Image:
- Copy the Endpoint ID for your
.envfile
Configure Local Tool
Add to your .env:
RUNPOD_API_KEY=your_api_key_here
RUNPOD_ENDPOINT_ID=your_endpoint_id_here
Use It
python tools/dewatermark.py \
--input video.mp4 \
--region 1080,660,195,40 \
--output clean.mp4 \
--runpod
Image Details
| Property | Value |
|---|---|
| Base | nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04 |
| Size | ~4GB |
| Cold Start | ~30 seconds |
| Python | 3.10 |
| PyTorch | 2.4.0 + CUDA 12.4 |
Pre-baked Components
- ProPainter repository
- Model weights (~2GB):
- ProPainter.pth
- recurrent_flow_completion.pth
- raft-things.pth
- i3d_rgb_imagenet.pt
- FFmpeg for video processing
- RunPod SDK
API Reference
Input Format
{
"input": {
"operation": "dewatermark",
"video_url": "https://example.com/video.mp4",
"region": "1080,660,195,40",
"resize_ratio": 0.75
}
}
| Parameter | Required | Description |
|---|---|---|
operation |
Yes | Must be "dewatermark" |
video_url |
Yes | Direct URL to video file |
region |
One of | Watermark region as "x,y,width,height" |
mask_url |
One of | URL to mask image (white = remove) |
resize_ratio |
No | Scale factor for processing (default: "auto" or 0.5). Use 1.0 for full resolution on short videos (<30s), 0.75 for <1min, 0.5 for longer |
Example with mask:
{
"input": {
"operation": "dewatermark",
"video_url": "https://example.com/video.mp4",
"mask_url": "https://example.com/mask.png"
}
}
Output Format
{
"success": true,
"output_url": "https://runpod-storage.../job123_dewatermarked.mp4",
"video_dimensions": "1920x1080",
"video_duration_seconds": 45.5,
"gpu_vram_gb": 24,
"profile_used": {
"subvideo_length": 60,
"neighbor_length": 10,
"ref_stride": 10
},
"processing_time_seconds": 120.5
}
Error Format
{
"error": "Description of what went wrong"
}
GPU Memory Profiles
The handler auto-detects GPU VRAM and selects optimal settings:
| VRAM | subvideo_length | neighbor_length | ref_stride | Speed |
|---|---|---|---|---|
| 8GB | 30 | 5 | 25 | Slow |
| 12GB | 40 | 5 | 20 | Medium |
| 16GB | 50 | 8 | 15 | Good |
| 24GB | 60 | 10 | 10 | Fast |
| 48GB | 80 | 10 | 10 | Fastest |
Recommendation: Use RTX 3090 or RTX 4090 (24GB) for best price/performance.
Cost Estimates
Using RTX 3090 (~$0.34/hr):
| Video Length | Processing Time | Estimated Cost |
|---|---|---|
| < 30 seconds | 2-5 minutes | ~$0.02 |
| 30s - 2 min | 5-15 minutes | ~$0.08 |
| 2 - 5 min | 15-45 minutes | ~$0.25 |
| > 5 min | 45+ minutes | ~$0.40+ |
Local Testing
Test the image locally with NVIDIA GPU:
# Build
docker build -t propainter-test .
# Run interactive shell
docker run --gpus all -it propainter-test /bin/bash
# Inside container, test GPU
python3 -c "import torch; print(f'CUDA: {torch.cuda.is_available()}')"
# Test handler with mock job
python3 -c "
from handler import handler
result = handler({
'id': 'test123',
'input': {
'operation': 'dewatermark',
'video_url': 'https://example.com/test.mp4',
'region': '100,100,50,50'
}
})
print(result)
"
Troubleshooting
"CUDA out of memory"
The video is too long for the GPU. Options:
- Use a GPU with more VRAM
- The local tool will auto-chunk long videos (coming soon)
"Failed to download video"
- Check the video URL is publicly accessible
- URLs must be direct downloads (not web pages)
- Timeout is 5 minutes for download
"No output file found"
ProPainter failed silently. Check:
- Video format is supported (MP4, MOV, AVI)
- Mask dimensions match video dimensions
- Region coordinates are valid
Cold start is slow
First request after idle takes ~30s to load models. Subsequent requests are faster. Consider:
- Setting longer idle timeout (but costs more)
- Using "always on" worker for frequent usage
Extending for New Operations
The handler is designed for extensibility. To add a new GPU operation:
-
Add handler function in
handler.py:def handle_upscale(job_input: dict, job_id: str, work_dir: Path) -> dict: # Implementation pass -
Register in main handler:
if operation == "upscale": return handle_upscale(job_input, job_id, work_dir) -
Rebuild and push image
Future operations might include:
upscale- Video upscaling with Real-ESRGANdenoise- Audio/video denoisingstabilize- Video stabilization