From 58fab2b2a4b6a57138280608ab2668797391294f Mon Sep 17 00:00:00 2001 From: "hehihoho3@gmail.com" Date: Wed, 5 Aug 2026 10:28:30 +0900 Subject: [PATCH] =?UTF-8?q?bg=5Fanalyze=EA=B0=80=20=EA=B5=AC=EA=B0=84=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=EB=A5=BC=20ranges=5Fsec/raw=5Fplaces/places?= =?UTF-8?q?=EB=A1=9C=20state=EC=97=90=20=EB=8B=B4=EB=8A=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 구간 탭에서 댓글 카드를 컷 단위로 배치하려면 "구간 N이 압축 타임라인의 어디인지"를 알아야 한다. 지금까지는 유튜브 구간을 다운로드·병합만 하고 그 경계 정보를 버렸다. 원본 시각(ranges_sec), 병합본 누적 구간 (raw_places), 무음 제거 후 압축 타임라인 구간(places)을 state에 추가한다. 파일 탭은 세 키 모두 빈 리스트로 유지되어 동작이 바뀌지 않는다(회귀 검증 완료). Co-Authored-By: Claude Opus 5 (1M context) --- capcut_agent/pipeline.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/capcut_agent/pipeline.py b/capcut_agent/pipeline.py index 395193e..bda5dbc 100644 --- a/capcut_agent/pipeline.py +++ b/capcut_agent/pipeline.py @@ -12,7 +12,7 @@ from __future__ import annotations import asyncio import os import time -from typing import AsyncIterator, Dict, List +from typing import AsyncIterator, Dict, List, Tuple from typing import Optional @@ -227,9 +227,21 @@ async def bg_analyze( t_all = time.perf_counter() use_gemini = has_gemini_key() + # 구간 탭이 "구간 N이 타임라인의 어디인지" 알아야 자막·배치·장수를 컷 단위로 낼 수 있다. + # 파일 탭(유튜브 아님)은 빈 리스트 → 아무 데서도 안 쓰인다. + ranges_sec: List[Tuple[float, float]] = [] + raw_places: List[Tuple[float, float]] = [] + # ── 유튜브 여러 구간 다운로드 + 병합 (URL 입력 시) ── if youtube: ranges = youtube.get("ranges") or [(youtube.get("start", ""), youtube.get("end", ""))] + from .paste import parse_time + c = 0.0 + for s, e in ranges: + ss, ee = parse_time(str(s)), parse_time(str(e)) + ranges_sec.append((ss, ee)) + raw_places.append((c, c + (ee - ss))) + c += ee - ss yield {"type": "step", "id": "download", "status": "start"} rng_txt = ", ".join(f"{s}~{e}" for s, e in ranges) yield {"type": "log", "msg": f"유튜브 {len(ranges)}개 구간 다운로드·병합 중… [{rng_txt}]"} @@ -264,6 +276,8 @@ async def bg_analyze( yield {"type": "error", "message": "오디오가 없거나 전부 무음입니다."} return kept = sum(e - s for s, e in keep) + # raw_places(병합본 좌표) → 압축 타임라인 좌표. 자막·배치·장수는 전부 이걸 쓴다. + places = _remap_placements(raw_places, keep) if raw_places else [] await _floor(t) yield {"type": "step", "id": "silence", "status": "done", "elapsed": round(time.perf_counter() - t, 1), @@ -307,6 +321,7 @@ async def bg_analyze( "video_clips": video_clips, "captions": captions, "total": total, "draft_name": draft_name, "title_top": title_top, "title_main": title_main, "channel": channel, "t_all": t_all, + "ranges_sec": ranges_sec, "raw_places": raw_places, "places": places, }}