Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions skills/fal-upscale/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
---
name: fal-upscale
description: Upscale and enhance image resolution using AI. Use when the user requests "Upscale image", "Enhance resolution", "Make image bigger", "Increase quality", or similar upscaling tasks.
description: Upscale and enhance image resolution using fal.ai or Atlas Cloud. Use when the user requests "Upscale image", "Enhance resolution", "Make image bigger", "Increase quality", or similar upscaling tasks.
metadata:
author: fal-ai
version: "1.0.0"
---

# fal.ai Upscale
# Image Upscale

Upscale and enhance image resolution using state-of-the-art AI models.
Upscale and enhance image resolution using fal.ai by default, with Atlas Cloud
available as an optional image provider.

## How It Works

1. User provides image URL and optional scale factor
2. Script selects appropriate upscaling model
3. Sends request to fal.ai API
3. Sends the request to the selected provider
4. Returns upscaled image URL

## Image Upscale Models
Expand All @@ -24,6 +25,7 @@ Upscale and enhance image resolution using state-of-the-art AI models.
| `fal-ai/aura-sr` | 4x | General upscaling, fast |
| `fal-ai/clarity-upscaler` | 2-4x | Detail preservation |
| `fal-ai/creative-upscaler` | 2-4x | Creative enhancement |
| `atlascloud/image-upscaler` | 1-4x | Optional Atlas Cloud provider |

## Video Upscale Models

Expand All @@ -45,8 +47,10 @@ bash /mnt/skills/user/fal-upscale/scripts/upscale.sh [options]

**Arguments:**
- `--image-url` - URL of image to upscale (required)
- `--provider` - `fal` (default) or `atlas`
- `--model` - Model ID (defaults to `fal-ai/aura-sr`)
- `--scale` - Upscale factor: 2 or 4 (default: 4)
- `--scale` - Upscale factor (default: 4; Atlas accepts 1-4)
- `--output-format` - Atlas output format: `jpeg`, `png`, `webp`, or `jpg`

**Examples:**

Expand All @@ -61,6 +65,14 @@ bash /mnt/skills/user/fal-upscale/scripts/upscale.sh \
--model "fal-ai/clarity-upscaler" \
--scale 2

# Image upscale with Atlas Cloud (4x, PNG)
export ATLASCLOUD_API_KEY="your_key_here"
bash /mnt/skills/user/fal-upscale/scripts/upscale.sh \
--provider atlas \
--image-url "https://example.com/image.jpg" \
--scale 4 \
--output-format png

# Video upscale (general purpose)
bash /mnt/skills/user/fal-upscale/scripts/upscale.sh \
--video-url "https://example.com/video.mp4" \
Expand All @@ -84,6 +96,19 @@ mcp__fal-ai__generate({
})
```

## Atlas Cloud Provider

Atlas uses the `atlascloud/image-upscaler` model. The script submits one image
generation request and polls the returned prediction with bounded backoff; it
does not retry the generation submission. Input images must be available at a
public URL. Video upscaling remains available through the default fal provider.

Set the credential before use:

```bash
export ATLASCLOUD_API_KEY="your_key_here"
```

## Output

```
Expand Down Expand Up @@ -144,6 +169,9 @@ To fix:
2. Set: export FAL_KEY=your_key_here
```

For Atlas Cloud, set `ATLASCLOUD_API_KEY` instead. Get a key from
https://www.atlascloud.ai/.

### Image URL Error
```
Error: Could not fetch image from URL
Expand All @@ -159,6 +187,6 @@ Make sure:
Network error. To fix on claude.ai:

1. Go to https://claude.ai/settings/capabilities
2. Add *.fal.ai to the allowed domains
2. Add `*.fal.ai` for fal, or `api.atlascloud.ai` for Atlas Cloud, to the allowed domains
3. Try again
```
144 changes: 134 additions & 10 deletions skills/fal-upscale/scripts/upscale.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
#!/bin/bash

# fal.ai Upscale Script
# Usage: ./upscale.sh --image-url URL [--model MODEL] [--scale SCALE]
# Image Upscale Script
# Usage: ./upscale.sh --image-url URL [--provider fal|atlas] [options]
# Returns: JSON with upscaled image URL

set -e

FAL_API_ENDPOINT="https://fal.run"
ATLAS_API_ENDPOINT="${ATLAS_API_ENDPOINT:-https://api.atlascloud.ai/api/v1}"
CURL_BIN="${CURL_BIN:-curl}"
SLEEP_BIN="${SLEEP_BIN:-sleep}"

# Default values
PROVIDER="fal"
MODEL="fal-ai/aura-sr"
MODEL_SET=false
IMAGE_URL=""
SCALE=4
OUTPUT_FORMAT="png"

# Check for --add-fal-key first
for arg in "$@"; do
Expand Down Expand Up @@ -49,22 +55,33 @@ while [[ $# -gt 0 ]]; do
;;
--model)
MODEL="$2"
MODEL_SET=true
shift 2
;;
--provider)
PROVIDER="$2"
shift 2
;;
--scale)
SCALE="$2"
shift 2
;;
--output-format)
OUTPUT_FORMAT="$2"
shift 2
;;
--help|-h)
echo "fal.ai Upscale Script" >&2
echo "Image Upscale Script" >&2
echo "" >&2
echo "Usage:" >&2
echo " ./upscale.sh --image-url URL [options]" >&2
echo "" >&2
echo "Options:" >&2
echo " --image-url Image URL to upscale (required)" >&2
echo " --model Model ID (default: fal-ai/aura-sr)" >&2
echo " --provider Provider: fal or atlas (default: fal)" >&2
echo " --model Provider model ID" >&2
echo " --scale Scale factor (default: 4)" >&2
echo " --output-format Atlas output format: jpeg, png, webp, or jpg" >&2
echo " --add-fal-key Setup FAL_KEY in .env" >&2
exit 0
;;
Expand All @@ -74,18 +91,51 @@ while [[ $# -gt 0 ]]; do
esac
done

# Validate required inputs
if [ -z "$FAL_KEY" ]; then
if [ -z "$IMAGE_URL" ]; then
echo "Error: --image-url is required" >&2
exit 1
fi

if [[ "$PROVIDER" != "fal" && "$PROVIDER" != "atlas" ]]; then
echo "Error: --provider must be fal or atlas" >&2
exit 1
fi

if [ "$PROVIDER" = "fal" ] && [ -z "$FAL_KEY" ]; then
echo "Error: FAL_KEY not set" >&2
echo "" >&2
echo "Run: ./upscale.sh --add-fal-key" >&2
echo "Or: export FAL_KEY=your_key_here" >&2
exit 1
fi

if [ -z "$IMAGE_URL" ]; then
echo "Error: --image-url is required" >&2
exit 1
if [ "$PROVIDER" = "atlas" ]; then
if [ -z "$ATLASCLOUD_API_KEY" ]; then
echo "Error: ATLASCLOUD_API_KEY not set" >&2
echo "Get a key at https://www.atlascloud.ai/ and export it before running." >&2
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
echo "Error: jq is required for the Atlas provider" >&2
exit 1
fi
if [ "$MODEL_SET" = false ]; then
MODEL="atlascloud/image-upscaler"
elif [ "$MODEL" != "atlascloud/image-upscaler" ]; then
echo "Error: Atlas currently supports atlascloud/image-upscaler only" >&2
exit 1
fi
if [[ ! "$SCALE" =~ ^[1-4]([.]0)?$ ]]; then
echo "Error: Atlas --scale must be between 1 and 4" >&2
exit 1
fi
case "$OUTPUT_FORMAT" in
jpeg|png|webp|jpg) ;;
*)
echo "Error: --output-format must be jpeg, png, webp, or jpg" >&2
exit 1
;;
esac
fi

# Create temp directory
Expand All @@ -94,6 +144,80 @@ trap 'rm -rf "$TEMP_DIR"' EXIT

echo "Upscaling with $MODEL..." >&2

if [ "$PROVIDER" = "atlas" ]; then
PAYLOAD=$(jq -nc \
--arg model "$MODEL" \
--arg image "$IMAGE_URL" \
--argjson outscale "$SCALE" \
--arg output_format "$OUTPUT_FORMAT" \
'{model:$model,image:$image,outscale:$outscale,output_format:$output_format}')

RESPONSE_FILE="$TEMP_DIR/atlas-submit.json"
HTTP_STATUS=$("$CURL_BIN" -sS -o "$RESPONSE_FILE" -w "%{http_code}" \
-X POST "$ATLAS_API_ENDPOINT/model/generateImage" \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")
API_CODE=$(jq -r '.code // 200' "$RESPONSE_FILE" 2>/dev/null || echo "invalid")

if [[ ! "$HTTP_STATUS" =~ ^2 ]] || [ "$API_CODE" != "200" ]; then
ERROR_MSG=$(jq -r '.msg // .message // .error // empty' "$RESPONSE_FILE" 2>/dev/null)
echo "Error: Atlas submission failed: ${ERROR_MSG:-HTTP $HTTP_STATUS}" >&2
exit 1
fi

PREDICTION_ID=$(jq -r '.data.id // .id // empty' "$RESPONSE_FILE")
if [ -z "$PREDICTION_ID" ]; then
echo "Error: Atlas submission returned no prediction ID" >&2
exit 1
fi

MAX_POLLS="${ATLAS_MAX_POLLS:-30}"
POLL_DELAY="${ATLAS_POLL_INTERVAL:-2}"
MAX_DELAY="${ATLAS_MAX_POLL_INTERVAL:-10}"
POLL_FILE="$TEMP_DIR/atlas-poll.json"

for ((attempt = 1; attempt <= MAX_POLLS; attempt++)); do
"$SLEEP_BIN" "$POLL_DELAY"
HTTP_STATUS=$("$CURL_BIN" -sS -o "$POLL_FILE" -w "%{http_code}" \
"$ATLAS_API_ENDPOINT/model/prediction/$PREDICTION_ID" \
-H "Authorization: Bearer $ATLASCLOUD_API_KEY")
API_CODE=$(jq -r '.code // 200' "$POLL_FILE" 2>/dev/null || echo "invalid")

if [[ "$HTTP_STATUS" =~ ^2 ]] && [ "$API_CODE" = "200" ]; then
STATUS=$(jq -r '(.data.status // .status // "") | ascii_downcase' "$POLL_FILE")
if [[ "$STATUS" == "completed" || "$STATUS" == "succeeded" ]]; then
OUTPUT_URL=$(jq -r '.data.outputs[0] // .outputs[0] // .data.output[0] // .output[0] // empty' "$POLL_FILE")
if [ -z "$OUTPUT_URL" ]; then
echo "Error: Atlas prediction returned no output URL" >&2
exit 1
fi
echo "Upscale complete!" >&2
echo "" >&2
echo "Image URL: $OUTPUT_URL" >&2
jq -nc --arg url "$OUTPUT_URL" --arg model "$MODEL" \
'{image:{url:$url},model:$model,provider:"atlas"}'
exit 0
fi
if [ "$STATUS" = "failed" ]; then
ERROR_MSG=$(jq -r '.data.error // .error // "unknown error"' "$POLL_FILE")
echo "Error: Atlas prediction failed: $ERROR_MSG" >&2
exit 1
fi
fi

if (( POLL_DELAY < MAX_DELAY )); then
POLL_DELAY=$((POLL_DELAY * 2))
if (( POLL_DELAY > MAX_DELAY )); then
POLL_DELAY="$MAX_DELAY"
fi
fi
done

echo "Error: Atlas prediction timed out after $MAX_POLLS checks" >&2
exit 1
fi

# Build payload based on model
if [[ "$MODEL" == *"aura-sr"* ]]; then
# AuraSR has fixed 4x scale
Expand All @@ -115,7 +239,7 @@ EOF
fi

# Make API request
RESPONSE=$(curl -s -X POST "$FAL_API_ENDPOINT/$MODEL" \
RESPONSE=$("$CURL_BIN" -s -X POST "$FAL_API_ENDPOINT/$MODEL" \
-H "Authorization: Key $FAL_KEY" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")
Expand Down
Loading