Tutorial API Bigjpg: besarkan imej secara pukal dengan Python
Skrip yang terus boleh dijalankan untuk memuat naik imej, mencipta tugasan pembesaran, menyemak hasil dan memuat turunnya, termasuk kawalan keselarian dan pengendalian ralat supaya kerja 500 imej tidak berhenti separuh jalan.
Untuk beberapa keping imej, antara muka web sudah memadai. Kalau folder anda ada lima ratus fail, API lebih menyenangkan: empat endpoint, tiada pelayar, dan skrip boleh dijalankan berulang kali. Versi di bawah inilah yang kami berikan terus kepada rakan sekerja: muat naik, cipta, semak, muat turun, sekali dengan pengendalian kegagalan yang benar-benar berguna.
Sebelum mula
- Akses API hanya untuk akaun berbayar. Kunci ada di halaman API selepas anda log masuk dengan pelan yang masih aktif.
- Python 3 dengan
requestsdipasang. Tiada apa-apa lagi. - Pembesaran berjalan secara tak segerak pada worker kami, jadi skrip mencipta tugasan dahulu, kemudian menyemaknya. Kerja 500 imej mengambil masa selama tugasan paling perlahan dalam baris gilir anda, bukan jumlah keseluruhan imej.
Skrip
import json
import os
import time
import requests
API = "https://bigjpg.com"
KEY = "YOUR_API_KEY"
STYLE = "art" # "art" untuk ilustrasi, "photo" untuk gambar foto
NOISE = "1" # -1 tiada, 0 rendah, 1 sederhana, 2 tinggi, 3 tertinggi
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":
# Cuba sekali lagi, kalau gagal lepaskan fail ini.
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:])
Apa setiap panggilan lakukan
| Panggilan | Tujuan | Catatan |
|---|---|---|
| POST /api/img_upload | Kembalikan URL muat naik bertandatangan dan URL imej awam | Muat naik fail dengan PUT menggunakan Content-Type yang sama, kemudian guna fileurl sebagai input tugasan |
| POST /api/task/ | Cipta tugasan pembesaran | Kembalikan tid, minute anggaran dan remaining_api_calls |
| GET /api/task/{ids} | Status satu atau banyak tugasan | id dipisahkan koma, sehingga 100 setiap permintaan |
| POST /api/task/{ids} | Cuba semula tugasan yang gagal | Hanya tugasan berstatus error kembali ke baris gilir |
Keselarian dan adab
- Semak dengan jarak yang lebih longgar. Pembesaran tidak serta-merta; 5–10 saat antara semakan sudah cukup, dan bertanya 100 id sekali gus mengekalkan bilangan permintaan.
- Hadkan muat naik. Dua hingga empat muat naik serentak adalah siling yang munasabah untuk satu mesin. Perlukan daya pemprosesan lebih, jalankan lebih banyak instans, bukan lebih banyak benang setiap instans.
- Cuba semula dengan kelewatan bertambah. Ralat rangkaian bukan kegagalan tugasan. Ulang panggilan HTTP sehingga tiga kali dengan jeda yang makin panjang sebelum fail dianggap rosak.
- Perhatikan
remaining_api_calls. Setiap tugasan yang dicipta melaporkannya; hentikan gelung pada ambang rendah daripada mengetahui hadnya melalui dinding ralat. - Simpan pemetaan. Kekalkan fail yang mengandungi
tid, nama input, tetapan dan nama output. Bila kerja berjalan sepanjang malam, fail itu satu-satunya cara mengetahui apa yang sudah siap.
Ralat yang pasti anda temui
valid_api_key_required— header tiada atau kunci tidak dikenali. Periksa nama header dan pastikan pelan kunci itu belum tamat tempoh.requires_vip— akaun percuma atau sudah tamat. API untuk pelan berbayar yang aktif.month_limit— kuota bulanan habis. Baki dilaporkan pada setiap tugasan, jadi anda boleh berhenti sebelum itu.param_error—stylemesti art atau photo,noise-1 hingga 3,x21 hingga 4.input_url_error— input mesti URL imej http atau https yang boleh diakses awam. URL peribadi bertandatangan akan tamat tempoh; muat naik dahulu, kemudian hantar URL awam yang dikembalikan.
Kos satu kelompok
Satu imej dikira satu kredit pada 2x, 4x dan 8x; pada 16x dikira dua. Jadi 500 imej pada 4x bermakna 500 kredit, dan kerja yang sama pada 16x menjadi 1000. Oleh sebab 4x memang faktor yang betul untuk kebanyakan gambar foto, pilihan yang lebih murah biasanya juga yang lebih elok — sebabnya ada dalam panduan faktor.
Rujukan lengkap endpoint, termasuk parameter dan semua status ralat, ada di halaman API. Kalau ada bahagian skrip yang tidak sepadan dengan respons anda, halaman itu versi yang kami kemas kini.