58 lines
2.3 KiB
Python
58 lines
2.3 KiB
Python
"""③ upscale — Topaz Text Refine 2배.
|
|
|
|
공개 채널의 공연 포스터는 전부 750px대라 그대로는 못 쓴다. Bytedance Upscale은 광선을
|
|
재작화하고 글자에 없던 무늬를 그려서(MAE 13 vs 5) Text Refine만 쓴다.
|
|
목적은 확대보다 GIF 128색 밴딩 해소다 — 밴딩이 남으면 생성 모델이 그것을 무늬로 읽는다.
|
|
"""
|
|
import io
|
|
import tempfile
|
|
from contextlib import contextmanager
|
|
from pathlib import Path
|
|
|
|
import httpx
|
|
from PIL import Image
|
|
|
|
from models.upscale import UpscaleResult
|
|
from settings import settings
|
|
from utils.higgsfield import (TOPAZ_IMAGE, TOPAZ_TEXT_REFINE, assert_account,
|
|
parse_result_url, run_cli)
|
|
|
|
OUTPUT_WIDTH, OUTPUT_HEIGHT = 1500, 2000
|
|
UPSCALE_CREDITS = 2
|
|
CLI_TIMEOUT = 420
|
|
MIN_IMAGE_BYTES = 10_000
|
|
|
|
|
|
@contextmanager
|
|
def as_png_path(image: bytes | Path):
|
|
"""CLI의 --image가 파일 경로만 받으므로 임시 파일로 내린다.
|
|
|
|
NOL 포스터는 팔레트 GIF(모드 P)로 오는데 그대로 올리면 잡이 failed로 돌아온다.
|
|
RGB PNG로 정규화해 보낸다.
|
|
"""
|
|
source = Image.open(image if isinstance(image, Path) else io.BytesIO(image))
|
|
with tempfile.NamedTemporaryFile(suffix=".png") as handle:
|
|
source.convert("RGB").save(handle, "PNG")
|
|
handle.flush()
|
|
yield Path(handle.name)
|
|
|
|
|
|
async def upscale_poster(poster: bytes | Path) -> UpscaleResult:
|
|
await assert_account(settings.higgsfield_account) # 크레딧 쓰기 전에
|
|
|
|
with as_png_path(poster) as source:
|
|
output = await run_cli(
|
|
"generate", "create", TOPAZ_IMAGE, "--image", str(source),
|
|
"--output_width", str(OUTPUT_WIDTH), "--output_height", str(OUTPUT_HEIGHT),
|
|
"--variant", TOPAZ_TEXT_REFINE, "--wait", "--wait-timeout", "4m", "--json",
|
|
timeout=CLI_TIMEOUT)
|
|
|
|
async with httpx.AsyncClient(timeout=300, follow_redirects=True) as client:
|
|
response = await client.get(parse_result_url(output))
|
|
response.raise_for_status()
|
|
if len(response.content) < MIN_IMAGE_BYTES:
|
|
raise RuntimeError(f"업스케일 결과가 너무 작다 ({len(response.content)}바이트)")
|
|
|
|
return UpscaleResult(image=response.content, credits=UPSCALE_CREDITS,
|
|
variant=TOPAZ_TEXT_REFINE)
|