From c3556edb9db6b5f64295500a67d1c31ef42249ee Mon Sep 17 00:00:00 2001 From: "hehihoho3@gmail.com" Date: Tue, 4 Aug 2026 12:23:18 +0900 Subject: [PATCH] =?UTF-8?q?/auto/build=EA=B0=80=20card=5Fcuts=20=ED=8F=BC?= =?UTF-8?q?=20=ED=95=84=EB=93=9C=EB=A5=BC=20=EB=B0=9B=EC=95=84=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=B4=ED=94=84=EB=9D=BC=EC=9D=B8=EC=97=90=20=EB=84=98?= =?UTF-8?q?=EA=B9=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - auto_build 시그니처에 card_cuts 폼 필드 추가 - JSON 배열 문자열 파싱 (값 깨져도 빌드 계속) - job dict에 저장 후 process_paste 호출에 전달 - bool 필터링 강화: JSON true/false가 정수로 둔갑하지 않도록 이유: JSON의 true/false가 Python bool로 파싱되는데, bool이 int의 서브클래스라 isinstance(v, int)를 통과해 컷 인덱스 1/0으로 대신 쓰이는 문제 해결. capcut_agent/recommend.py 패턴과 일관성 있음. Co-Authored-By: Claude Opus 5 (1M context) --- server/app.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/app.py b/server/app.py index f75eed2..3e85c73 100644 --- a/server/app.py +++ b/server/app.py @@ -224,6 +224,7 @@ async def stream(job_id: str) -> StreamingResponse: asr_bottom=job.get("asr_bottom", False), name_suffix=job.get("name_suffix", ""), cards_fixed=job.get("cards_fixed", False), + card_cuts=job.get("card_cuts") or None, ) else: stream_iter = process_bg_template( @@ -610,6 +611,7 @@ async def auto_build( remove_silence: str = Form(""), asr_bottom: str = Form(""), cards_fixed: str = Form(""), + card_cuts: str = Form(""), ) -> JSONResponse: """자동 탭 빌드 — 붙여넣기 스키마 JSON + 카드 PNG들 → 기존 paste job. @@ -634,6 +636,14 @@ async def auto_build( body = await f.read() with open(os.path.join(cdir, f"{i:03d}.png"), "wb") as out: out.write(body) + # 카드별 소속 컷 — 값이 깨져도 빌드를 막지 않는다(없으면 기존 전체 균등 배치) + cut_map: list[int] = [] + try: + parsed = json.loads(card_cuts) if card_cuts.strip() else [] + if isinstance(parsed, list): + cut_map = [int(v) for v in parsed if isinstance(v, int) and not isinstance(v, bool)] + except (json.JSONDecodeError, ValueError, TypeError): + cut_map = [] JOBS[h] = { "paste": payload, "draft_name": f"auto_{h}", "video_scale": _scale(video_scale), "flip": _truthy(flip), @@ -641,6 +651,7 @@ async def auto_build( "bg_white": _truthy(bg_white), "remove_silence": _truthy(remove_silence), "asr_bottom": _truthy(asr_bottom), "name_suffix": safe_tag, "cards_fixed": _truthy(cards_fixed), + "card_cuts": cut_map, } return JSONResponse({"job_id": h, "cuts": len(payload["cuts"]), "cards": len(cards)})