악역영애 말포이
뉴스레터코드 vs AI프롬프트 원문집파이프라인 그래프도구별 파이프라인효과 사전키트 README상태 공간 STATE프롬프트 README에이전트 배선도
목차

03 파이프라인 그래프: 악역영애 말포이 영상 제작 (LangGraph 스타일)


① 전체 그래프

전체 파이프라인 그래프

사용자 interrupt 되돌림 지도

사용자 피드백 되돌림 지도


② State 스키마 (그래프가 들고 다니는 상태)

키 담는 것 실제 값 예 쓰는 노드
episode 현재 편 id·제목·길이·BPM V1 S-RANK PULL, 26.5s, 128.17 BPM 스토리보드
storyboard 컷 표(시간·마디·화면·소스·오디오), 편집 결정표(EDL) STORYBOARD.md S1~S7, V1-EDL.md 레이어 L0~L5 스토리보드
rules 누적 제약(사용자 피드백·사고 교훈) IP 단어 프롬프트 금지, 이미지 기반 Flow만, 의상 7벌, 영어 보컬, heavy 동시 2 interrupt·사고 대응
assets codex 이미지 경로 + 대조 결과 02_frames/S4_fullbody.png, outfits/O1~O7, turnaround.png, v3/V3_C02~C22 이미지 생성·스왑 교정
flow_jobs 잡 정의(첫·끝 프레임, 초, 프롬프트, 모드) 06_flow/v1_jobs.json 11잡, ref 4, extra 9, v3 7, v4 10 스토리보드
clips Flow 결과 mp4 + 판정(채택/주의/재생성) + 재생성 횟수 06_flow/v1/V1_S4.mp4 채택, R1_orbit_blue_r2 채택(주의) Flow 판정
mattes 알파 webm + QC 시트 + 초/프레임 05_matte/v1/V1_S4.webm, V1_S4_qc.jpg 매팅
audio 곡 마스터·박 시각표·VO·SFX 04_audio/bgm/BGM_MAIN_aligned.wav, beats.json(히트 3.773/7.484/…) 오디오
blocks 코드 배경 블록 html + 변수 03_motion/compositions/kinetic_wall.html 등 7종 + mm-lib.js 코드 배경 블록
renders 패스·드래프트·최종·업로드본·컨택트시트 07_render/v1/build/pass_bg.mp4·draft_540p.mp4 → V1_SRANK_PULL.mp4 합성·렌더
feedback 사용자 반려 원문 + 되돌릴 노드 "좆같다, 영어로" → 오디오 곡 후보 생성 interrupt
budget Flow 크레딧, ElevenLabs 크레딧 잔액·상한 Flow 1,050 → 664 / ElevenLabs 47,676 → 67,151 사용 누계 Flow 제출·오디오 생성

③ 노드 표

노드 담당 입력 출력 실패·재시도 규칙
리서치 Claude 서브에이전트 + Aside 브라우저 사용자 요청, 레퍼런스 릴스 00_ref/research-meme.md, research-flow.md, 핀터레스트 122장 + 컨택트시트 무관 검색 결과(Gacha Life 등)는 전량 삭제 후 검색어 교체. 웹 조사는 Aside(firecrawl 금지)
스토리보드 메인 Claude 리서치, rules STORYBOARD·EDL·V3-STORYBOARD·V4-BRIEF, *_jobs.json, 크레딧 예산표 반려 시 이 노드로 복귀(4편 "도는 거 멋없다")
병렬 분기 메인 Claude storyboard 3갈래 동시 기동 의존 없는 갈래는 즉시 동시 기동
캐릭터 디자인 codex 4개 병렬(imagegen_runner.py) 정본 설정, 핀터레스트 참조 01_design/canon_{pony,drill,straight}.png, alt_slick.png 실패분만 재실행(이미 있는 파일 건너뜀)
첫 프레임·의상 codex 4개 병렬 정본 시안, 컷 표 02_frames/*(블루 #1E3CFF 합성용 / 인월드), 의상 7벌, 턴어라운드 IP 단어 금지, 이미지에 글자 넣지 않음(글자는 코드 층)
스왑 교정 메인 Claude 생성 이미지 + 컨택트시트 내용 기준으로 바로잡은 파일명 컨택트시트 육안 대조, 어긋나면 교정 후 재대조
에셋 업로드 Claude 서브에이전트 + Aside 이미지 경로 Flow 프로젝트 에셋 D: 직접 업로드는 거부됨 → Aside 세션 폴더 복사 후 업로드
360p 테스트 Flow(Aside) 첫 프레임 2장 06_flow/test/T1.mp4, T2.mp4 크레딧 상한 30
테스트 게이트 Claude 서브에이전트 테스트 클립 통과/불합격 + 프롬프트 교훈 기준: 컷 분할 0(scene>0.25 검출 0), 블루 유지, 얼굴 일관. 불합격 → 첫 프레임 노드
720p 배치 Flow(Aside) *_jobs.json 06_flow/<배치>/*.mp4 동시 5~6개, 생성 직전 비용 표시값으로 단가 검증, 화면에 "실패·오류·정책" 뜨면 중단
클립 판정 Claude 서브에이전트 클립 LOG.md 행(채택/주의/재생성 대상) 재생성 1회만(_r2). 2회째도 흠이면 주의 채택 → 후반에서 크롭·컷 구간 선택으로 회피
매팅 로컬 GPU(Windows DirectML) + WSL 키어 블루 컷 mp4 05_matte/<배치>/*.webm + _qc.jpg GPU 실패 → 그 컷만 CPU 재시도. .part.webm로 쓰고 끝나면 이름 변경. 인월드 컷 건너뜀
곡 후보 생성 Claude 서브에이전트 + ElevenLabs Music composition_plan 요청 JSON bgm/*.mp3, v3/song/*, v4/cand/* 동시 요청 2개(넘으면 429). 편별 크레딧 상한(1편 25,000 등)
오디오 실측·선택 Claude 서브에이전트(파이썬 분석) 후보 곡 BPM·드롭·브레이크·가사 인식 표, 선택 곡 기준 미달 시 요청 수정 후 재생성. 가사는 demucs 보컬 분리 후 whisper 받아쓰기로 판정
편집 마스터 Claude 서브에이전트 선택 곡 *_MAIN.wav + beats.json 모델이 지시한 브레이크·끝 히트를 안 지키면 편집으로 만듦(앞 자르기·무음·끝 히트 붙이기)
VO·SFX Claude 서브에이전트 + ElevenLabs v4 TTS·SFX 대사 표 vo/final/*, sfx/* 목소리 오디션(F0·ASR 비교), 테이크 2개씩, 오인식 테이크는 _rejected/
코드 배경 블록 Claude 서브에이전트 워커 A·B·C 스토리보드, beats.json, awesome-ai-motion 기법 03_motion/compositions/*.html 7종 hyperframes check lint 0. 클립월은 모니터 12대·ffmpeg 순차로 제한
합류 메인 Claude 매팅·인월드 클립·오디오·블록 편별 합성 착수 3갈래가 다 차야 진행
배경·전경 패스 로컬 CPU(HyperFrames, heavy.sh) 블록 + 오디오 pass_bg.mp4, pass_fg.mov(1편) / bgchar.mp4(3·5편) / plates.mp4·타이포 스프라이트(4편) 알파 webm은 HyperFrames 안에 넣지 않음
알파 합성 Claude 서브에이전트(파이썬·ffmpeg) 패스 + 알파 webm + EDL 합성 영상 1편 composite.py, 3·5편 charcomp.sh, 4편 comp4.py(numpy 프레임 합성)
드래프트 540p 로컬 CPU 합성 설정 draft_540p.mp4, v4_540_r1~r3.mp4 반복 확인은 draft 품질
컨택트시트 판정 메인 Claude 1초 간격 타일 통과/수정 지시 배치·박 정합·자막 안전지대 어긋나면 합성으로 복귀
최종 렌더 로컬 CPU(heavy.sh 2슬롯, Windows 렌더 가능) 통과한 합성 07_render/V*_*.mp4 1080x1920, 라우드니스 -14 LUFS 빈 슬롯 날 때까지 대기, --workers ≤ 2~4
업로드본 로컬 CPU 최종본 V4_HYPER_EDIT_upload.mp4(CRF 21), V*_contact.jpg -
사용자 피드백 사용자(interrupt) 업로드본 승인 / 반려 원문 반려 → 되돌림 지도대로 원인 노드 복귀, rules에 누적
인계 메인 Claude 전 산출 HANDOFF·설명 폴더·_layers 다음 편 있으면 스토리보드로

단계별 세부 워크플로

기획

이미지

Flow

매팅

오디오

코드 배경 블록

합성·렌더


④ 시퀀스: 1편 S4 한 컷이 이미지에서 합성까지

1편 S4 한 컷 시퀀스


⑤ 실제 LangGraph 코드로 옮긴다면 (의사코드, 실행 안 함)

# 의사코드: 실제 파이프라인은 LangGraph 없이 메인 Claude 오케스트레이션 + 셸 큐로 돌렸음
from typing import Annotated, TypedDict
import operator
from langgraph.graph import StateGraph, START, END
from langgraph.types import Send, interrupt, Command

class S(TypedDict):
    storyboard: dict; rules: list; assets: dict; budget: dict; feedback: str
    clips: Annotated[list, operator.add]; mattes: Annotated[list, operator.add]
    blocks: Annotated[list, operator.add]; audio: dict; renders: dict

g = StateGraph(S)
for n in ["research", "storyboard", "design", "frames", "swap_fix", "flow_test",
          "flow_job", "matte", "audio", "block", "join", "composite", "draft", "final", "handoff"]:
    g.add_node(n, NODES[n])          # NODES = 각 노드 함수(codex·Aside·ElevenLabs·로컬 호출)

g.add_edge(START, "research"); g.add_edge("research", "storyboard")
# 병렬 분기: 이미지 갈래 1 + 오디오 1 + 블록 워커 3
g.add_conditional_edges("storyboard", lambda s: [Send("design", s), Send("audio", s)]
                        + [Send("block", {**s, "worker": w}) for w in "ABC"])
g.add_edge("design", "frames")
g.add_conditional_edges("frames", lambda s: "swap_fix" if names_mismatch(s) else "flow_test")
g.add_edge("swap_fix", "frames")      # 교정 후 재대조
g.add_conditional_edges("flow_test", lambda s: "frames" if not test_ok(s) else
                        [Send("flow_job", j) for j in s["storyboard"]["flow_jobs"]])   # 동시 5~6
g.add_conditional_edges("flow_job", route_clip)   # 재생성 1회 → flow_job / 블루 컷 → matte / 인월드 → join
g.add_edge(["matte", "audio", "block"], "join")   # 합류(fan-in)
g.add_edge("join", "composite"); g.add_edge("composite", "draft")
g.add_conditional_edges("draft", lambda s: "final" if contact_sheet_ok(s) else "composite")

def final(s):                         # heavy.sh 세마포어: 동시 2
    with HEAVY_SLOTS: render(s, workers=2)
    fb = interrupt({"upload": s["renders"]["upload"]})   # 사용자 피드백에서 멈춤
    if fb["approved"]: return Command(goto="handoff")
    return Command(goto=RETURN_MAP[fb["reason"]],        # 예: "korean_vocal" → "audio"
                   update={"rules": [fb["rule"]], "feedback": fb["text"]})

g.add_conditional_edges("handoff", lambda s: "storyboard" if s["storyboard"]["next"] else END)
app = g.compile(checkpointer=SqliteSaver("malfoy.db"))   # WSL 재부팅에도 재개

⑥ 실제로 막혔던 지점과 그래프상 대응 노드

막힌 지점 무슨 일 대응 그래프 노드
과부하로 WSL 재부팅 (10-07 20:08) 렌더·매팅 워커 9기 동시 + 클립월 렌더가 ffmpeg 30개 동시(모니터 31대 버전) + 에이전트들이 /mnt/d 전체 폰트 검색 → 로드 160, RAM 2GB, 세션 끊김 _tools/heavy.sh 동시 2 세마포어(flock 슬롯 2개 + nice), render --workers ≤ 2, 클립월 12대·ffmpeg 순차, /mnt/d 전체 find 금지 최종 렌더 · 드래프트 · 배경 패스 · 코드 배경 블록(클립월) · 매팅
C 드라이브 차오름 WSL 홈이 물리적으로 C(ext4.vhdx)라 캐시·venv·임시 파일이 C를 채움 매팅 venv·모델·pip 캐시·Windows TEMP, Windows 렌더 도구 전부 D:\_cache로, 산출은 처음부터 /mnt/d 매팅 · 최종 렌더(Windows)
알파 렌더 느려짐·멈춤 위험 HyperFrames 렌더가 screenshot capture(느린 경로)로 떨어짐. 로그 경고 "Heavy compositions can stall on software GL". 1편 전경 패스 26.5초에 1분 55초·223MB, 3편 드래프트 30초에 9분 알파 webm을 HyperFrames에 직접 넣지 않음. HyperFrames는 배경·전경 패스만, 캐릭터 알파 합성은 파이썬·ffmpeg로(charcomp.sh 주석 그대로) 배경·전경 패스 · 알파 합성
TMPDIR SIGILL TMPDIR=/mnt/d/...로 렌더하면 Chrome이 SIGILL로 죽어 capture 실패 env -u TMPDIR로 기본 임시 경로 유지, 프레임 캐시만 HYPERFRAMES_EXTRACT_CACHE_DIR=/mnt/d/_cache/... 드래프트 · 최종 렌더(이 문서의 Mermaid 렌더도 같은 규칙)
이미지 내용↔파일명 스왑 러너가 codex 공용 폴더에서 "가장 최근·미회수 PNG"를 집어 감 → 4개 병렬일 때 늦게 끝난 잡이 남의 그림을 가져감. 3편 15장 컨택트시트(00_SHEETS/5_3편이미지15장_이름교정전순서.jpg)를 파일명 순서로 보면 C03 파일에 C06 테이블 장면, C04 파일에 C03 입장 장면이 들어가는 식으로 엇갈림 컨택트시트로 내용 대조 후 이름 교정, Flow 쪽은 3중 대조(프롬프트·제안 파일명·타일 의상)로 오배정 0 스왑 교정 · 클립 판정
한국어 보컬 반려 (10-07 21시) 3편 한국어 OP 곡(K9, 인식 0.8)을 사용자가 "영어로" 반려. ElevenLabs 한국어 노래 보컬 품질 불만 영어 12후보 생성 → E11 선택 → 5편 V5_ROFAN_OP_EN. 규칙: 노래는 영어 보컬 기본, 한국어는 VO·자막만 사용자 interrupt → 곡 후보 생성
텍스트만 Flow 생성 반려 이미지 없이 프롬프트만으로 Flow를 돌려 사용자 질책 순서 고정: codex 이미지(시트·첫 프레임) → Flow 에셋 → 이미지 기반 생성 사용자 interrupt → 캐릭터 디자인
의상 고정 반려 전 컷이 교복 한 벌 의상 7벌(가챠 스킨식) + 머리 3종, 포니 약 40% 사용자 interrupt → 첫 프레임·의상
소재 모드 배경 붕괴 참조 모드(R1·R4)에서 블루가 하늘색 그라데이션+바닥 그림자로 나옴, 동영상 참조 시 출력 3초로 줄어듦 재생성 1회(_r2) 후 주의 채택, 합성 컷은 프레임 모드 우선 클립 판정 → 재생성 루프
ElevenLabs 429 곡 동시 요청이 상한(2개)을 넘자 429 거부 곡은 2개씩 생성 곡 후보 생성