File size: 14,199 Bytes
873dee2 1ddf1f6 873dee2 1ddf1f6 873dee2 1ddf1f6 d761612 1ddf1f6 6d1ca30 26041a6 1ddf1f6 76f7693 6a5300e 1ddf1f6 9106134 1ddf1f6 9106134 6a5300e 9106134 6a5300e 9106134 6a5300e 9106134 6a5300e 9106134 6a5300e 9106134 1ddf1f6 9106134 1ddf1f6 9106134 1ddf1f6 9106134 6d1ca30 9106134 6d1ca30 9106134 873dee2 9106134 5bc6fce 9106134 873dee2 9106134 96bd52c 6c3c1b3 8a73758 22b54dd 9106134 22b54dd 8a73758 22b54dd 8a73758 22b54dd 6c3c1b3 22b54dd 3ed7d57 9106134 3ed7d57 22b54dd 8a73758 22b54dd 3ed7d57 22b54dd 6c3c1b3 9106134 1ddf1f6 9106134 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | import os, sys, requests, re, time
import httpx
# =========================================================
# رفع قطعی مشکل 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, handle_file
prompt = os.environ.get('PROMPT', '')
image_url_raw = os.environ.get('IMAGE_URL', '')
# تجزیه و تفکیک لینکها از متغیر مشترک گیتهاب
urls = image_url_raw.split(',')
image_url = urls[0] if len(urls) > 0 else ""
image_url2 = urls[1] if len(urls) > 1 else ""
image_url3 = urls[2] if len(urls) > 2 else ""
run_id = os.environ.get('RUN_ID')
space_url = os.environ.get('SPACE_URL')
github_run_id = os.environ.get('GITHUB_RUN_ID')
# هماهنگی کامل با سیستم هوشمند تلاش مجدد و بررسی خطاهای شبکه
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,
"image_url2": image_url2,
"image_url3": image_url3,
"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}")
def check_existing_edited_image(space_url, run_id):
"""بررسی اینکه آیا تصویر ویرایش شده در تلاش قبلی آپلود شده است یا خیر"""
for ext in ['png', 'webp', 'jpg']:
url = f"{space_url}/static/images/{run_id}.{ext}"
try:
# استفاده از GET سبک با stream=True برای سازگاری کامل با تمامی سرورها
res = requests.get(url, stream=True, timeout=10)
if res.status_code == 200:
return url, ext
except:
pass
return None, None
print('1. Checking if edited image already exists on Docker Space...')
existing_url, existing_ext = None, None
if run_id:
existing_url, existing_ext = check_existing_edited_image(space_url, run_id)
filename = 'output.png'
ext = 'png'
# اگر تصویر ویرایش شده از قبل موجود بود، نیازی به فرآیند ادیت مجدد نیست
if existing_url:
print(f' -> Edited image already exists: {existing_url}')
print(' -> Skipping Omni Editor pipeline. Proceeding directly to CodeFormer upscaling...')
ext = existing_ext
filename = f'output.{ext}'
try:
img_req = requests.get(existing_url, timeout=60)
with open(filename, 'wb') as f:
f.write(img_req.content)
print(f' -> Downloaded existing edited image as {filename}')
except Exception as dl_err:
print(f' -> Failed to download existing image: {dl_err}. Re-running Omni Editor...')
existing_url = None
if not existing_url:
print('1. Downloading input images from Docker Space...')
try:
req = requests.get(image_url, timeout=30)
with open('input.png', 'wb') as f:
f.write(req.content)
print(' -> Input image 1 ready.')
except Exception as e:
err_str = f"Download failed for image 1: {e}"
print(err_str)
report_failure(err_str)
sys.exit(1)
# دانلود اختیاری تصویر دوم
has_image2 = False
if image_url2 and image_url2.strip():
try:
req2 = requests.get(image_url2, timeout=30)
with open('input2.png', 'wb') as f:
f.write(req2.content)
has_image2 = True
print(' -> Input image 2 ready.')
except Exception as e:
print(f" -> Image 2 optional download warning (skipped): {e}")
# دانلود اختیاری تصویر سوم
has_image3 = False
if image_url3 and image_url3.strip():
try:
req3 = requests.get(image_url3, timeout=30)
with open('input3.png', 'wb') as f:
f.write(req3.content)
has_image3 = True
print(' -> Input image 3 ready.')
except Exception as e:
print(f" -> Image 3 optional download warning (skipped): {e}")
print('2. Connecting to Omni Editor and Processing (Timeout extended to 300s)...')
result_str = ''
success = False
# مکانیزم تلاش مجدد در صورت شلوغی سرور
for attempt in range(3):
try:
print(f' -> Attempt {attempt + 1} of 3...')
client = Client('selfit-camera/omni-image-editor')
# اگر فقط تصویر اول آپلود شده باشد، مثل سابق رفتار کن
if not (has_image2 or has_image3):
print(' -> Processing with single-image pipeline (exact same as before)...')
result = client.predict(
handle_file('input.png'),
prompt,
api_name='/edit_image_interface'
)
# اگر چند تصویر آپلود شده باشند، از هوک چند تصویری استفاده کن
else:
print(' -> Processing with multi-image pipeline (fn_index=10)...')
result = client.predict(
handle_file('input.png'),
handle_file('input2.png') if has_image2 else None,
handle_file('input3.png') if has_image3 else None,
prompt,
'Auto', # نسبت تصویر پیشفرض
fn_index=10
)
result_str = str(result)
if 'src=' in result_str or 'http' in result_str:
success = True
break
else:
print(f' -> Missing valid response format: {result_str[:100]}...')
except Exception as client_err:
print(f' -> Attempt {attempt + 1} failed: {client_err}')
time.sleep(5)
if not success:
err_str = f"All attempts failed. Raw result: {result_str}"
print(f'CRITICAL ERROR: {err_str}')
report_failure(err_str)
sys.exit(1)
print('3. Parsing result string...')
urls = re.findall(r'src=[\'\"]([^\'\"]+)[\'\"]', result_str)
final_remote_url = None
for url in urls:
if url.startswith('http'):
final_remote_url = url
break
elif url.startswith('/'):
# برای تبدیل آدرسهای نسبی محلی گرادیو به آدرس کامل و قابل دانلود
final_remote_url = f"https://selfit-camera-omni-image-editor.hf.space{url}"
break
if not final_remote_url:
direct_urls = re.findall(r'(https?://[^\s\'\"]+\.(?:png|jpg|jpeg|webp|gif))', result_str)
if direct_urls:
final_remote_url = direct_urls[0]
if not final_remote_url:
err_str = f"Could not find valid URL. Raw result: {result_str}"
print(f'ERROR: {err_str}')
report_failure(err_str)
sys.exit(1)
print(f' -> Found Final Image URL: {final_remote_url}')
print('4. Downloading final image from remote host...')
try:
img_req = requests.get(final_remote_url, timeout=60)
content_type = img_req.headers.get('Content-Type', '')
ext = 'png'
if 'image/webp' in content_type:
ext = 'webp'
elif 'image/jpeg' in content_type or 'image/jpg' in content_type:
ext = 'jpg'
filename = f'output.{ext}'
with open(filename, 'wb') as f:
f.write(img_req.content)
print(f' -> Saved locally as {filename}')
except Exception as dl_err:
err_str = f"Failed to download processed image: {dl_err}"
print(err_str)
report_failure(err_str)
sys.exit(1)
print(f'4.2. Uploading edited image to Docker Space: {space_url}')
try:
with open(filename, '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(' -> Edited image uploaded successfully.')
else:
print(f' -> Edited image upload failed: {res.status_code} - {res.text}')
except Exception as up_err:
print(f' -> Edited image upload exception: {up_err}')
# =========================================================
# بخش بهبودیافته: تلاش چندجانبه برای ارتباط موفق با API اسپیس CodeFormer
print('4.5. Connecting to CodeFormer to restore and upscale (Factor=4, Fidelity=1.0)...')
cf_success = False
try:
cf_client = Client('sczhou/CodeFormer')
upscale_result = None
# ساختار مانیتورینگ متدهای متوالی برای جلوگیری از بروز خطای api_name
methods_to_try = [
# روش ۱: استفاده از ایندکس صفر به همراه ساختار ۶ پارامتری (ویرایش جدید اسپیس)
{"args": [handle_file(filename), True, True, True, 4, 1.0], "kwargs": {"fn_index": 0}},
# روش ۲: استفاده از ایندکس صفر به همراه ساختار ۵ پارامتری (نسخههای پایدار قدیمی)
{"args": [handle_file(filename), True, True, 4, 1.0], "kwargs": {"fn_index": 0}},
# روش ۳: تلاش با ایندکس یک به همراه ساختار ۶ پارامتری
{"args": [handle_file(filename), True, True, True, 4, 1.0], "kwargs": {"fn_index": 1}},
# روش ۴: تلاش با ایندکس یک به همراه ساختار ۵ پارامتری
{"args": [handle_file(filename), True, True, 4, 1.0], "kwargs": {"fn_index": 1}},
# روش ۵: فراخوانی اسمی بدون اسلش (predict) با ساختار ۶ پارامتری
{"args": [handle_file(filename), True, True, True, 4, 1.0], "kwargs": {"api_name": "predict"}},
# روش ۶: فراخوانی اسمی بدون اسلش (predict) با ساختار ۵ پارامتری
{"args": [handle_file(filename), True, True, 4, 1.0], "kwargs": {"api_name": "predict"}},
# روش ۷: فراخوانی اسمی با اسلش (/predict) با ساختار ۶ پارامتری
{"args": [handle_file(filename), True, True, True, 4, 1.0], "kwargs": {"api_name": "/predict"}},
# روش ۸: فراخوانی اسمی با اسلش (/predict) با ساختار ۵ پارامتری
{"args": [handle_file(filename), True, True, 4, 1.0], "kwargs": {"api_name": "/predict"}},
]
for idx, method in enumerate(methods_to_try):
try:
print(f' -> Trying execution path {idx + 1} of {len(methods_to_try)}...')
upscale_result = cf_client.predict(*method["args"], **method["kwargs"])
if upscale_result:
print(f' -> Success! CodeFormer handled by path {idx + 1}.')
break
except Exception as method_err:
print(f' -> Path {idx + 1} bypassed: {method_err}')
upscale_path = None
if isinstance(upscale_result, list) and len(upscale_result) > 0:
upscale_path = upscale_result[0]
elif isinstance(upscale_result, tuple) and len(upscale_result) > 0:
upscale_path = upscale_result[0]
elif isinstance(upscale_result, dict):
upscale_path = upscale_result.get('image') or upscale_result.get('path')
else:
upscale_path = upscale_result
if upscale_path and os.path.exists(str(upscale_path)):
print(f' -> CodeFormer Success! Output saved at {upscale_path}')
upscale_ext = 'png'
if str(upscale_path).endswith('.webp'):
upscale_ext = 'webp'
elif str(upscale_path).endswith('.jpg') or str(upscale_path).endswith('.jpeg'):
upscale_ext = 'jpg'
print(f' -> Uploading quality-enhanced image as: {run_id}_upscaled')
with open(upscale_path, 'rb') as f_up:
res_up = requests.post(
f'{space_url}/api/webhook/upload',
data={'run_id': f"{run_id}_upscaled", 'github_run_id': github_run_id, 'ext': upscale_ext},
files={'file': f_up},
timeout=60
)
if res_up.status_code == 200:
print(' -> Enhanced image uploaded successfully.')
cf_success = True
else:
print(f' -> Enhanced image upload failed: {res_up.status_code} - {res_up.text}')
else:
print(' -> Warning: CodeFormer did not return a valid file path.')
except Exception as cf_err:
print(f' -> Warning: CodeFormer process bypassed or failed: {cf_err}')
# =========================================================
if not cf_success:
err_str = "CodeFormer upscaling failed or was bypassed due to ZeroGPU/Gradio connection limits."
print(f'CRITICAL WARNING: {err_str}')
report_failure(err_str)
sys.exit(1) # بازگرداندن وضعیت خطا به رانر گیتهاب تا فرآیند تلاش مجدد را تا ۲۰ بار تکرار کند
print('6. SUCCESS! Process finished successfully.') |