runflare / yml /generate-editor.py
Sada8888's picture
کوین
6d1ca30 verified
Raw
History Blame Contribute Delete
8.79 kB
import os, sys, random, requests, json, time, base64
import httpx
from PIL import Image
# =========================================================
# رفع قطعی مشکل Time Out رانر گیت‌هاب با تنظیم زمان انتظار به ۵ دقیقه
original_client_init = httpx.Client.__init__
def patched_client_init(self, *args, **kwargs):
kwargs['timeout'] = httpx.Timeout(300.0)
original_client_init(self, *args, **kwargs)
httpx.Client.__init__ = patched_client_init
original_async_init = httpx.AsyncClient.__init__
def patched_async_init(self, *args, **kwargs):
kwargs['timeout'] = httpx.Timeout(300.0)
original_async_init(self, *args, **kwargs)
httpx.AsyncClient.__init__ = patched_async_init
# =========================================================
from gradio_client import Client
prompt = os.environ.get('PROMPT', '')
image_url = os.environ.get('IMAGE_URL', '')
run_id = os.environ.get('RUN_ID')
space_url = os.environ.get('SPACE_URL')
github_run_id = os.environ.get('GITHUB_RUN_ID')
# دریافت متغیرهای عددی با مقادیر پیش‌فرض هماهنگ با فرانت‌اند جدید
try:
steps = int(os.environ.get('STEPS', '15'))
except:
steps = 15
try:
guidance_scale = float(os.environ.get('GUIDANCE', '1.0'))
except:
guidance_scale = 1.0
def report_failure(error_msg):
try:
requests.post(
f"{space_url}/api/webhook/fail",
json={
"run_id": run_id,
"error": error_msg,
"event_type": "generate-editor",
"client_payload": {
"prompt": prompt,
"image_url": image_url,
"run_id": run_id,
"space_url": space_url
},
"github_run_id": github_run_id
},
timeout=15
)
except Exception as e:
print(f"Failed to report failure: {e}")
print('1. Downloading input image from Docker Space...')
local_input_path = 'input_to_edit.png'
try:
req = requests.get(image_url, timeout=30)
with open(local_input_path, 'wb') as f:
f.write(req.content)
print(' -> Input image ready.')
except Exception as e:
err_str = f"Download failed: {e}"
print(err_str)
report_failure(err_str)
sys.exit(1)
print('2. Extracting exact original dimensions and preparing Base64 Data URI...')
try:
# استخراج ابعاد دقیق پیکسلی کاربر برای بازنشانی نهایی
img = Image.open(local_input_path)
orig_width, orig_height = img.size
print(f' -> Target Exact Size required by User: {orig_width}x{orig_height}')
# تبدیل تصویر دانلود شده به فرمت کد دیتا (Base64 Data URI) همانطور که اسپیس جدید نیاز دارد
with open(local_input_path, "rb") as img_file:
encoded_string = base64.b64encode(img_file.read()).decode('utf-8')
base64_data_uri = f"data:image/png;base64,{encoded_string}"
# ساخت ساختار آرایه رشته‌ای جی‌سون (JSON String of Images Array)
images_json_payload = json.dumps([base64_data_uri])
print(' -> Base64 payload generated successfully.')
except Exception as e:
err_str = f"Failed to prepare image data payload: {e}"
print(err_str)
report_failure(err_str)
sys.exit(1)
print('3. Connecting to Qwen Image Edit Space (Fast LoRA)...')
success = False
raw_result = None
for attempt in range(3):
try:
print(f' -> Attempt {attempt + 1} of 3...')
# اتصال به آدرس اسپیس جدید معرفی شده در فرانت‌اند شما
client = Client("https://prithivmlmods-qwen-image-edit-2511-loras-fast.hf.space/")
seed = random.randint(1, 2147483647)
lora_adapter = "Anything2Real" # استایل پیش‌فرض برای تبدیل به عکس طبیعی و واقعی
randomize_seed = True
# ارسال پارامترها دقیقاً منطبق با Predict شماره 2 اسپیس مقصد
result = client.predict(
images_json_payload, # پارامتر اول: رشته جی‌سون تصاویر
prompt, # پارامتر دوم: دستور متنی
lora_adapter, # پارامتر سوم: نام آداپتور لورا
seed, # پارامتر چهارم: سید عددی
randomize_seed, # پارامتر پنجم: رندوم کردن سید
guidance_scale, # پارامتر ششم: مقدار Guidance Scale
steps, # پارامتر هفتم: تعداد مراحل پردازش
fn_index=2 # مشخص کردن اجرای ایندکس شماره ۲ API
)
if result:
raw_result = result
success = True
break
except Exception as client_err:
print(f' -> Attempt {attempt + 1} failed: {client_err}')
time.sleep(5)
if not success or not raw_result:
err_str = "Qwen-Image-Edit Space failed to process the image after 3 attempts."
print(f'CRITICAL ERROR: {err_str}')
report_failure(err_str)
sys.exit(1)
print('4. Resolving and downloading generated output image...')
local_output_path = 'output_raw.png'
try:
# استخراج مسیر فایل یا لینک دانلود از پاسخ Gradio Client
if isinstance(raw_result, (tuple, list)):
res_data = raw_result[0]
elif isinstance(raw_result, dict):
res_data = raw_result.get('data', [None])[0] or raw_result
else:
res_data = raw_result
if isinstance(res_data, dict):
output_url_or_path = res_data.get('url') or res_data.get('path')
else:
output_url_or_path = str(res_data)
# اگر خروجی یک لینک وب بود آن را دانلود کن، در غیر این صورت فایل محلی را بخوان
if output_url_or_path.startswith('http'):
img_req = requests.get(output_url_or_path, timeout=60)
with open(local_output_path, 'wb') as f:
f.write(img_req.content)
else:
if os.path.exists(output_url_or_path):
import shutil
shutil.copy(output_url_or_path, local_output_path)
else:
raise FileNotFoundError(f"Result file path not found: {output_url_or_path}")
print(' -> Output downloaded and ready for post-processing.')
except Exception as extract_err:
err_str = f"Failed to resolve processed image output: {extract_err}. Raw response was: {raw_result}"
print(err_str)
report_failure(err_str)
sys.exit(1)
print('5. Post-Processing: Precisely resizing back to match user original size...')
try:
# باز کردن تصویر تولید شده جهت اعمال تغییر ابعاد نهایی
generated_img = Image.open(local_output_path)
# تغییر سایز با بالاترین کیفیت ممکن (فیلتر Lanczos) به ابعاد دقیق پیکسل اولیه کاربر
final_resized_img = generated_img.resize((orig_width, orig_height), Image.Resampling.LANCZOS)
# ذخیره نهایی بر روی دیسک
final_resized_img.save(local_input_path)
print(f' -> Done! Output image matches perfectly with original size: {orig_width}x{orig_height} px.')
except Exception as resize_err:
print(f' -> Warning: High precision resizing failed ({resize_err}). Using raw output.')
import shutil
shutil.copy(local_output_path, local_input_path)
print('6. Preparing image file extension metadata...')
ext = 'png'
try:
with Image.open(local_input_path) as verify_img:
content_type = verify_img.format
if content_type == 'WEBP': ext = 'webp'
elif content_type in ['JPEG', 'JPG']: ext = 'jpg'
except:
ext = 'png'
print(f'7. Uploading processed natural photo back to Docker Space: {space_url}')
try:
with open(local_input_path, 'rb') as f:
res = requests.post(
f'{space_url}/api/webhook/upload',
data={'run_id': run_id, 'github_run_id': github_run_id, 'ext': ext},
files={'file': f},
timeout=60
)
if res.status_code == 200:
print('8. SUCCESS! Qwen-Image-Edit workflow finished perfectly.')
else:
err_str = f"Upload to Docker webhook failed: {res.status_code} - {res.text}"
print(err_str)
report_failure(err_str)
sys.exit(1)
except Exception as up_err:
err_str = f"Failed to upload result to webhook: {up_err}"
print(err_str)
report_failure(err_str)
sys.exit(1)