Spaces:
Running
Running
Download test_kontext.py from AswinMathew/anime-gen-api: direct link, hf CLI and curl.
- Browser
- Download file 4.65 kB
-
https://huggingface.co/spaces/AswinMathew/anime-gen-api/resolve/main/test_kontext.py
- Command line
-
hf download hf://spaces/AswinMathew/anime-gen-api/test_kontext.py
-
curl -L -o test_kontext.py https://huggingface.co/spaces/AswinMathew/anime-gen-api/resolve/main/test_kontext.py
4.65 kB
| """Test NVIDIA NIM FLUX.1 Kontext-dev for consistent frame variant generation.""" | |
| import asyncio | |
| import base64 | |
| import os | |
| import time | |
| from pathlib import Path | |
| import httpx | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| NVIDIA_API_KEY = os.getenv("NVIDIA_API_KEY") | |
| KONTEXT_URL = "https://ai.api.nvidia.com/v1/genai/black-forest-labs/flux.1-kontext-dev" | |
| # Try to find an existing generated image | |
| WORKDIR = Path("workdir/projects/2/images") | |
| async def generate_test_keyframe() -> bytes: | |
| """Generate a fresh manhwa-style keyframe via HF FLUX.1-schnell.""" | |
| hf_token = os.getenv("HF_TOKEN") | |
| prompt = ( | |
| "manhwa style, korean webtoon art, sharp lineart, cel-shaded, " | |
| "close-up shot, young adult male, jet black messy hair, deep crimson eyes, " | |
| "black high-collar coat, dramatic lighting, vibrant colors, detailed background" | |
| ) | |
| async with httpx.AsyncClient(timeout=30) as client: | |
| resp = await client.post( | |
| "https://huggingface.co/proxy/api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell", | |
| headers={"Authorization": f"Bearer {hf_token}"}, | |
| json={"inputs": prompt}, | |
| ) | |
| resp.raise_for_status() | |
| return resp.content | |
| async def kontext_edit(image_b64: str, prompt: str) -> bytes: | |
| """Send an image to Kontext for editing.""" | |
| async with httpx.AsyncClient(timeout=60) as client: | |
| resp = await client.post( | |
| KONTEXT_URL, | |
| headers={ | |
| "Authorization": f"Bearer {NVIDIA_API_KEY}", | |
| "Content-Type": "application/json", | |
| "Accept": "application/json", | |
| }, | |
| json={ | |
| "image": image_b64, | |
| "prompt": prompt, | |
| "steps": 25, | |
| "cfg_scale": 3.5, | |
| }, | |
| ) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| # Response format: {"artifacts": [{"base64": "..."}]} or {"data": [{"b64_json": "..."}]} | |
| if "artifacts" in data: | |
| return base64.b64decode(data["artifacts"][0]["base64"]) | |
| elif "data" in data: | |
| return base64.b64decode(data["data"][0]["b64_json"]) | |
| else: | |
| # Try direct b64 field | |
| for key in ("b64_json", "base64", "image"): | |
| if key in data: | |
| return base64.b64decode(data[key]) | |
| raise ValueError(f"Unknown response format: {list(data.keys())}") | |
| async def main(): | |
| if not NVIDIA_API_KEY: | |
| print("ERROR: NVIDIA_API_KEY not set in .env") | |
| return | |
| output_dir = Path("test_kontext_output") | |
| output_dir.mkdir(exist_ok=True) | |
| # Step 1: Get a keyframe image | |
| print("Step 1: Getting keyframe image...") | |
| keyframe_path = None | |
| # Try existing images first | |
| if WORKDIR.exists(): | |
| images = sorted(WORKDIR.glob("*.png")) | |
| if images: | |
| keyframe_path = images[0] | |
| print(f" Using existing image: {keyframe_path}") | |
| if keyframe_path: | |
| with open(keyframe_path, "rb") as f: | |
| keyframe_bytes = f.read() | |
| else: | |
| print(" Generating fresh keyframe via HF FLUX.1-schnell...") | |
| keyframe_bytes = await generate_test_keyframe() | |
| keyframe_path = output_dir / "00_keyframe.png" | |
| with open(keyframe_path, "wb") as f: | |
| f.write(keyframe_bytes) | |
| print(f" Saved keyframe: {keyframe_path}") | |
| # Save original | |
| orig_path = output_dir / "00_original.png" | |
| with open(orig_path, "wb") as f: | |
| f.write(keyframe_bytes) | |
| keyframe_b64 = base64.b64encode(keyframe_bytes).decode() | |
| # Step 2: Generate 3 variants | |
| edit_prompts = [ | |
| ("01_smile", "same scene, character now has a slight smile"), | |
| ("02_hand_raise", "same scene, character raises their right hand"), | |
| ("03_wind", "same scene, wind blowing through hair, clothes rippling"), | |
| ] | |
| for filename, prompt in edit_prompts: | |
| print(f"\nStep 2: Kontext edit - '{prompt}'...") | |
| t0 = time.time() | |
| try: | |
| variant_bytes = await kontext_edit(keyframe_b64, prompt) | |
| elapsed = time.time() - t0 | |
| out_path = output_dir / f"{filename}.png" | |
| with open(out_path, "wb") as f: | |
| f.write(variant_bytes) | |
| print(f" OK in {elapsed:.1f}s -> {out_path}") | |
| except Exception as e: | |
| elapsed = time.time() - t0 | |
| print(f" FAILED in {elapsed:.1f}s: {e}") | |
| print(f"\nDone! Check {output_dir}/ for results.") | |
| print("Visual check: Are faces/proportions/colors consistent enough for RIFE interpolation?") | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |