$ cat node-template.py
Image Upscale
// Upscales an image to higher resolution using Real-ESRGAN via a native GPU service. Accepts an image and a configurable upscale factor (2-4x). Outputs the upscaled image.
Process
Image
template.py
1import os2import sys3import json4import subprocess5import time6import traceback78try:9 import requests10except ImportError:11 subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"])12 import requests1314NATIVE_IMAGE_UPSCALE_SERVICE_URL = os.getenv(15 "NATIVE_IMAGE_UPSCALE_SERVICE_URL", "http://native-image-upscale-service:8102"16)17_EMBLEMA_VERSION = os.getenv("EMBLEMA_VERSION", "dev")18NATIVE_IMAGE_UPSCALE_SERVICE_IMAGE = os.getenv(19 "NATIVE_IMAGE_UPSCALE_SERVICE_IMAGE",20 f"emblema/native-image-upscale-service:{_EMBLEMA_VERSION}",21)22HF_CACHE_HOST_PATH = os.getenv("HF_CACHE_HOST_PATH", "/root/.cache/huggingface")23CONTAINER_NAME = "native-image-upscale-service"24INPUT_DIR = "/data/input"25OUTPUT_DIR = "/data/output"262728def start_container():29 """Create and start native-image-upscale-service, removing any stale container first."""30 subprocess.run(31 ["docker", "rm", "-f", CONTAINER_NAME],32 capture_output=True, text=True33 )3435 hf_token = os.getenv("HUGGINGFACE_TOKEN", "")36 print(f"Creating container {CONTAINER_NAME}...", file=sys.stderr)37 run_cmd = [38 "docker", "run", "-d",39 "--name", CONTAINER_NAME,40 "--network", "emblema",41 "--gpus", "all",42 "-e", "PORT=8102",43 "-e", "DEVICE=cuda",44 "-e", f"HF_TOKEN={hf_token}",45 "-v", f"{HF_CACHE_HOST_PATH}:/root/.cache/huggingface",46 NATIVE_IMAGE_UPSCALE_SERVICE_IMAGE,47 ]48 result = subprocess.run(run_cmd, capture_output=True, text=True)49 if result.returncode != 0:50 print(f"docker run failed (exit {result.returncode}): {result.stderr}", file=sys.stderr)51 raise RuntimeError(f"Failed to start container: {result.stderr}")5253 # Poll health endpoint54 timeout = 18055 interval = 356 elapsed = 057 health_url = f"{NATIVE_IMAGE_UPSCALE_SERVICE_URL}/health"58 while elapsed < timeout:59 try:60 r = requests.get(health_url, timeout=5)61 if r.status_code == 200:62 print(f"Container healthy (waited {elapsed}s).", file=sys.stderr)63 return64 except requests.ConnectionError:65 pass66 time.sleep(interval)67 elapsed += interval6869 raise RuntimeError(f"Container did not become healthy within {timeout}s")707172def stop_container():73 """Remove the container."""74 try:75 subprocess.run(76 ["docker", "rm", "-f", CONTAINER_NAME],77 capture_output=True, text=True, timeout=3078 )79 print(f"Container {CONTAINER_NAME} removed.", file=sys.stderr)80 except Exception as e:81 print(f"Warning: failed to remove container: {e}", file=sys.stderr)828384def main():85 try:86 input_json = sys.stdin.read()87 execution_input = json.loads(input_json)88 inputs = execution_input.get("inputs", {})8990 image = inputs.get("image", "")91 upscale_factor = float(inputs.get("upscale_factor", 4))9293 if not image:94 raise ValueError("Image is required")95 if not (2 <= upscale_factor <= 4):96 raise ValueError(f"Upscale factor must be between 2 and 4, got {upscale_factor}")9798 local_path = os.path.join(INPUT_DIR, image)99 if not os.path.exists(local_path):100 raise FileNotFoundError(f"Input image not found: {local_path}")101102 os.makedirs(OUTPUT_DIR, exist_ok=True)103104 # Start the container105 start_container()106107 try:108 # Send image to service109 with open(local_path, "rb") as f:110 resp = requests.post(111 f"{NATIVE_IMAGE_UPSCALE_SERVICE_URL}/upscale",112 files={"image": (os.path.basename(local_path), f, "image/png")},113 data={"upscale_factor": str(upscale_factor)},114 timeout=600,115 )116117 if resp.status_code != 200:118 try:119 error_detail = resp.json()120 except Exception:121 error_detail = resp.text122 raise RuntimeError(123 f"Upscale service returned {resp.status_code}: {error_detail}"124 )125126 # Save result127 out_filename = "upscaled_result.png"128 out_path = os.path.join(OUTPUT_DIR, out_filename)129 with open(out_path, "wb") as f:130 f.write(resp.content)131132 inference_time = resp.headers.get("X-Inference-Time-Ms", "unknown")133 output_size = resp.headers.get("X-Output-Size", "unknown")134 print(135 f"Upscaled: factor={upscale_factor}, output_size={output_size}, time={inference_time}ms",136 file=sys.stderr,137 )138139 output = {140 "image": out_filename,141 }142 print(json.dumps(output, indent=2))143144 finally:145 stop_container()146147 except Exception as e:148 error_output = {149 "error": str(e),150 "errorType": type(e).__name__,151 "traceback": traceback.format_exc(),152 }153 print(json.dumps(error_output), file=sys.stderr)154 sys.exit(1)155156157if __name__ == "__main__":158 main()