Bigjpg API ट्यूटोरियल: Python से एक साथ कई इमेज बड़ी करें
चलाने के लिए तैयार स्क्रिप्ट, जो इमेज अपलोड करती है, एनलार्ज टास्क बनाती है, नतीजे पोल करती है और डाउनलोड करती है — साथ में वह कॉन्करेंसी और एरर हैंडलिंग जिससे 500 इमेज का काम बीच में नहीं अटकता।
कुछ इमेज के लिए वेब इंटरफ़ेस ठीक है। पाँच सौ फ़ाइलों वाले फ़ोल्डर के लिए API बेहतर है: चार endpoint, कोई ब्राउज़र नहीं, और स्क्रिप्ट जब चाहें दोबारा चलाइए। नीचे वही स्क्रिप्ट है जो हम सीधे किसी साथी को देते हैं, उस एरर हैंडलिंग के साथ जो असल में काम आती है।
शुरू करने से पहले
- API सिर्फ़ पेड अकाउंट के लिए है। सक्रिय प्लान के साथ लॉग इन करने पर आपकी key API पेज पर मिलती है।
- Python 3 और इंस्टॉल किया हुआ
requests। इसके अलावा कुछ नहीं। - एनलार्जिंग हमारे worker पर async चलती है, इसलिए स्क्रिप्ट पहले टास्क बनाती है और फिर पोल करती है। 500 इमेज का काम उतना समय लेता है जितना आपकी कतार में सबसे धीमा टास्क लेता है, इमेज की संख्या का जोड़ नहीं।
स्क्रिप्ट
import json
import os
import time
import requests
API = "https://bigjpg.com"
KEY = "YOUR_API_KEY"
STYLE = "art" # "art" इलस्ट्रेशन के लिए, "photo" तस्वीरों के लिए
NOISE = "1" # -1 कोई नहीं, 0 कम, 1 मध्यम, 2 ज़्यादा, 3 सबसे ज़्यादा
X2 = "2" # 1 = 2x, 2 = 4x, 3 = 8x, 4 = 16x
POLL_SECONDS = 8
MAX_RETRY = 1
HEADERS = {"X-API-KEY": KEY}
def upload(path):
"""Get a presigned URL, PUT the file, return its public URL."""
name = path.split("/")[-1]
r = requests.post(
API + "/api/img_upload",
headers=HEADERS,
data={"filename": name, "filetype": "image/jpeg"},
timeout=60,
)
info = r.json()
if info.get("status") != "ok":
raise RuntimeError("upload failed: " + str(info))
with open(path, "rb") as image:
r = requests.put(
info["url"],
data=image,
headers={"Content-Type": "image/jpeg"},
timeout=300,
)
if r.status_code != 200:
raise RuntimeError("upload failed with HTTP %s" % r.status_code)
return info["fileurl"]
def create(image_url):
"""Create an enlargement task, return its task id."""
payload = {
"style": STYLE,
"noise": NOISE,
"x2": X2,
"input": image_url,
}
r = requests.post(
API + "/api/task/",
headers=HEADERS,
data=json.dumps(payload),
timeout=60,
)
data = r.json()
if "tid" not in data:
raise RuntimeError("task failed: " + str(data))
return data["tid"]
def poll(tids):
"""Query up to 100 task ids at once. Returns task id -> result dict."""
r = requests.get(API + "/api/task/" + ",".join(tids), timeout=60)
return r.json()
def download(url, out):
"""Download a finished image, checking the transfer really succeeded."""
r = requests.get(url, timeout=300)
if r.status_code != 200:
raise RuntimeError("download failed with HTTP %s" % r.status_code)
with open(out, "wb") as f:
f.write(r.content)
return out
def main(paths):
pending = {}
attempts = {}
for path in paths:
try:
tid = create(upload(path))
except Exception as e:
print("skipped", path, e)
continue
pending[tid] = path
attempts[tid] = 0
print("queued", path, tid)
while pending:
for tid, info in poll(list(pending)[:100]).items():
if info.get("status") == "success":
out = os.path.splitext(pending[tid])[0] + "_bigjpg.jpg"
try:
download(info["url"], out)
except Exception as e:
print("download failed", pending[tid], e)
pending.pop(tid)
continue
print("done", pending.pop(tid), "->", out)
elif info.get("status") == "error":
# एक बार और कोशिश, फिर यह फ़ाइल छोड़ दें।
attempts[tid] += 1
if attempts[tid] <= MAX_RETRY:
requests.post(API + "/api/task/" + tid, headers=HEADERS, timeout=60)
print("retrying", pending[tid])
else:
print("giving up on", pending.pop(tid))
if pending:
time.sleep(POLL_SECONDS)
if __name__ == "__main__":
import sys
main(sys.argv[1:])
हर कॉल क्या करती है
| कॉल | काम | नोट |
|---|---|---|
| POST /api/img_upload | साइन किया हुआ अपलोड URL और इमेज का सार्वजनिक URL लौटाती है | फ़ाइल को उसी Content-Type के साथ PUT कीजिए, फिर fileurl को टास्क के input में दीजिए |
| POST /api/task/ | एनलार्ज टास्क बनाती है | tid, अनुमानित minute और remaining_api_calls लौटाती है |
| GET /api/task/{ids} | एक या कई टास्क का स्टेटस | id कॉमा से अलग, एक रिक्वेस्ट में 100 तक |
| POST /api/task/{ids} | फेल टास्क दोबारा चलाती है | सिर्फ़ error वाले टास्क कतार में वापस जाते हैं |
कॉन्करेंसी और तमीज़
- सोच से कम बार पोल कीजिए। एनलार्जिंग तुरंत नहीं होती; 5–10 सेकंड का अंतर काफ़ी है, और एक कॉल में 100 id पूछने से रिक्वेस्ट की संख्या कम रहती है।
- अपलोड सीमित रखिए। एक मशीन के लिए दो से चार अपलोड एक साथ ठीक सीमा है। ज़्यादा थ्रूपुट चाहिए तो हर इंस्टेंस में थ्रेड बढ़ाने की जगह इंस्टेंस बढ़ाइए।
- बढ़ती देरी के साथ दोबारा कोशिश। नेटवर्क एरर टास्क का फेल होना नहीं है। किसी फ़ाइल को खराब मानने से पहले HTTP कॉल तीन बार तक दोहराइए, हर बार लंबे इंतज़ार के साथ।
remaining_api_callsपर नज़र रखिए। बना हर टास्क यह बताता है; एरर की दीवार से सीमा जानने की जगह किसी कम थ्रेशोल्ड पर लूप रोक दीजिए।- मैपिंग लिखती रहिए।
tid, इनपुट नाम, सेटिंग और आउटपुट नाम वाली एक फ़ाइल रखिए। रातभर चलने वाले काम में यही लॉग बताता है कि क्या पूरा हुआ।
वे एरर जो असल में मिलेंगे
valid_api_key_required— हेडर गायब है या key अज्ञात। हेडर का नाम देखिए और यह भी कि key का प्लान एक्सपायर नहीं हुआ।requires_vip— मुफ़्त या एक्सपायर हो चुका अकाउंट। API सक्रिय पेड प्लान के लिए है।month_limit— महीने का कोटा खत्म। हर टास्क बचा हुआ कोटा बताता है, इसलिए उससे पहले रुक सकते हैं।param_error—styleart या photo होना चाहिए,noise-1 से 3,x21 से 4।input_url_error— input सार्वजनिक रूप से उपलब्ध http या https इमेज URL होना चाहिए। साइन किए निजी URL एक्सपायर हो जाते हैं; पहले अपलोड कीजिए, फिर लौटाया गया सार्वजनिक URL भेजिए।
बैच का खर्च
2x, 4x और 8x पर एक इमेज एक क्रेडिट है; 16x पर दो। यानी 500 इमेज 4x पर 500 क्रेडिट, और 16x पर 1000। चूँकि ज़्यादातर तस्वीरों के लिए 4x ही सही फैक्टर है, सस्ता विकल्प आम तौर पर ज़्यादा अच्छा दिखता भी है — पूरा तर्क फैक्टर गाइड में है।
पैरामीटर और हर एरर स्टेटस समेत पूरा endpoint रेफ़रेंस API पेज पर है। स्क्रिप्ट में कुछ आपको मिलने वाले जवाब से मेल न खाए, तो वही पेज हमारी अपडेटेड वर्शन है।