class DolphinBatchSeedController: """ 클립 4개짜리 파이프라인(First + Extend×3)의 영상 샘플러 시드를 한 곳에서 스위칭하기 위한 노드. 기존에는 클립마다 서로 다른 서브그래프 안에 묻힌 SeedGenerator 위젯을 4번 따로 조작해야 "매 배치 랜덤"과 "특정 클립부터 재생성"을 오갈 수 있었다. "seed"라는 이름의 INT 위젯에는 ComfyUI 프론트엔드가 자동으로 control_after_generate(fixed/increment/decrement/randomize) 드롭다운을 붙여준다 - 그래서 "전체 랜덤"/"특정 클립부터 재생성"에 필요한 새 시드는 이 위젯 하나의 randomize/increment만으로 나오고, 노드 자체는 매 실행 무작위를 호출할 필요 없는 순수 함수로 남는다. 주의: "특정 클립부터 재생성"이지 "그 클립만 재생성"이 아니다. Extend 서브그래프는 이전 클립의 실제 디코딩된 프레임을 입력으로 받는 continuity 구조라, N번 클립 시드를 바꾸면 N+1, N+2... 클립은 자기 시드값이 그대로여도 입력 latent가 달라져서 캐시가 깨지고 무조건 다시 렌더링된다. N보다 앞 클립들만 그대로 캐시된다. """ MODE_FIXED = "🔒 고정 (재현)" MODE_RANDOM_ALL = "🎲 전체 랜덤 (매 배치)" MODE_REGEN_FROM = "♻️ 특정 클립부터 재생성 (그 뒤 클립도 연쇄 재생성됨)" GOLDEN = 0x9E3779B97F4A7C15 MASK = 0xFFFFFFFFFFFFFFFF @classmethod def INPUT_TYPES(s): req = { "mode": ([s.MODE_FIXED, s.MODE_RANDOM_ALL, s.MODE_REGEN_FROM], {"default": s.MODE_FIXED}), "regen_clip": (["1", "2", "3", "4"], {"default": "1", "tooltip": "'특정 클립부터 재생성' 모드에서 몇 번 클립부터 새 시드를 줄지. " "그 클립 이후 클립들도 continuity 때문에 같이 다시 렌더링된다 " "(이전 클립들만 캐시 유지)."}), "seed": ("INT", {"default": 0, "min": 0, "max": s.MASK}), "c1_seed": ("INT", {"default": 196010661098274, "min": 0, "max": s.MASK}), "c2_seed": ("INT", {"default": 316514109857979, "min": 0, "max": s.MASK}), "c3_seed": ("INT", {"default": 732840722629067, "min": 0, "max": s.MASK}), "c4_seed": ("INT", {"default": 599880917933127, "min": 0, "max": s.MASK}), } return {"required": req} RETURN_TYPES = ("INT", "INT", "INT", "INT", "STRING") RETURN_NAMES = ("c1_seed", "c2_seed", "c3_seed", "c4_seed", "debug_info") FUNCTION = "get_seeds" CATEGORY = "Dolphin" def get_seeds(self, mode, regen_clip, seed, c1_seed, c2_seed, c3_seed, c4_seed): base = [c1_seed, c2_seed, c3_seed, c4_seed] if mode == self.MODE_RANDOM_ALL: out = [(seed + i * self.GOLDEN) & self.MASK for i in range(4)] elif mode == self.MODE_REGEN_FROM: out = list(base) out[int(regen_clip) - 1] = seed else: out = list(base) debug = f"mode={mode} | c1={out[0]} c2={out[1]} c3={out[2]} c4={out[3]}" print(f"🎲 [BatchSeedController] {debug}") return (*out, debug) NODE_CLASS_MAPPINGS = { "DolphinBatchSeedController": DolphinBatchSeedController, } NODE_DISPLAY_NAME_MAPPINGS = { "DolphinBatchSeedController": "🎲 Dolphin Batch Seed Controller (random-all / regen-from-clip)", }