# task-659.1 완료 보고서: ThreadAuto 영상 엔진 통합 + 시각 표현 강화

## S - Situation
ThreadAuto 영상 엔진이 3개(evan_dynamic.py/shortform_renderer.py/remotion/)로 파편화되어 있으며, Remotion 엔진의 시각 표현 수준이 6.5/10 수준(Unicode 문자 아이콘, 단일 레이아웃, 기본 애니메이션)으로 에반 6원칙 충족이 미흡한 상태다.

## C - Complication
파이프라인에서 생성된 slides JSON이 Remotion 영상으로 자동 변환되는 경로가 없고(미연결), TTS-영상 싱크 메커니즘도 미구현이라 실제 서비스 가능한 영상 자동 생산이 불가능했다. 또한 SCENE_GAP(0.4초)과 transitionDuration(0.5초) 불일치로 5장면 기준 0.5초 누적 오차가 발생했다.

## Q - Question
Remotion 단일 엔진으로 파이프라인을 통합하고, 시각 표현을 강화하여 "콘텐츠가 살아 움직이는 숏폼 영상"을 자동 생산할 수 있는가?

## A - Answer
7단계 파이프라인 오케스트레이터 신규 구현 + Remotion calculateMetadata/전장면 타이핑/SCENE_GAP 통일 + lucide-react 아이콘(5개 Scene) + 레이아웃 변형(5종 A/B) + 고급 애니메이션(글로우/틸트/easeOutExpo/Vignette) 적용 완료. Python 62테스트 통과, TypeScript 컴파일 에러 0건, pyright 에러 0건.

---

## 작업 내용

### A. Python 파이프라인 통합 (불칸)

**신규 파일**: `video/pipeline_orchestrator.py` (267줄)
- `extract_narration_texts()`: 슬라이드 타입별(cover/card_list/detail/body/cta) TTS 텍스트 추출
- `compose_scenes_with_durations()`: TTS 오디오 길이 기반 duration 오버라이드 + variant(A/B/C) 순환 할당
- `generate_shortform_video()`: 7단계 파이프라인 오케스트레이션 (slides→TTS→duration→scenes→render→mux)

**수정 파일**: `video/scene_composer.py`
- `compose_scenes()`에 `durations` 파라미터 추가 (하위호환 유지)
- variant 필드 자동 할당 로직 추가

**수정 파일**: `video/tts_sync.py`
- SCENE_GAP: 0.4 → 0.5초 (transitionDuration과 통일)

### B. Remotion TypeScript 수정 (이리스)

**Root.tsx**: `calculateMetadata` 추가 → 동적 scenes duration 기반 durationInFrames 자동 계산
**ShortForm/index.tsx**: Audio 컴포넌트 제거 (FFmpeg mux 방식으로 대체)
**evanTiming.ts**: SCENE_GAP: 15 (0.5초) 상수 추가
**shortform.ts**: SceneData에 `variant?: "A" | "B" | "C"` 필드 추가

### C. 시각 표현 강화 (이리스)

**전 장면 타이핑 효과**: 5개 Scene 모두에 useTypingEffect 적용 (에반 원칙 #4)

**lucide-react 아이콘 통합** (v0.577.0):
- HookScene: Sparkles (구분선 영역)
- ChecklistScene: CheckCircle (체크마크 교체, spring 바운스)
- DataScene: TrendingUp/DollarSign/Shield/PieChart (라벨 텍스트 기반 자동 선택)
- InfoScene: Info/Lightbulb/AlertTriangle (카드 인덱스 순환)
- CtaScene: ArrowUp/ExternalLink/Phone (역할별 배치)

**레이아웃 변형** (variant A/B):
- HookScene A(중앙)/B(좌측텍스트+우측아이콘)
- ChecklistScene A(세로리스트)/B(2열그리드)
- DataScene A(큰숫자중앙)/B(좌우분할)
- InfoScene A(카드나열)/B(좌우분할)
- CtaScene A(중앙집중)/B(하단배너+CTA버튼)

**고급 애니메이션**:
- 텍스트 글로우: 타이핑 완료 후 accent glow 페이드인
- 카드 틸트: ChecklistScene/InfoScene 카드 rotate(3°→0°) 등장
- easeOutExpo 카운터: DataScene CountUp에 적용
- 아이콘 spring 바운스: 모든 lucide 아이콘에 적용

**배경 효과**:
- Vignette: 5개 Scene 전체 radial-gradient 오버레이
- 그라데이션 시프트: frame 기반 배경 각도 변화

### D. Deprecated 처리

- `renderer/shortform_renderer.py`: DEPRECATED 주석 + warnings.warn(DeprecationWarning)
- `video/evan_dynamic.py`: DEPRECATED 주석 (구현 레퍼런스용 유지)
- `remotion/render_bridge.py`: slides_to_scenes() docstring에 DEPRECATED 주석

---

## 생성/수정 파일 목록

**신규**:
- `/home/jay/projects/ThreadAuto/video/pipeline_orchestrator.py`
- `/home/jay/projects/ThreadAuto/video/tests/test_pipeline_orchestrator.py`

**수정**:
- `video/scene_composer.py` — durations 파라미터 + variant 할당
- `video/tts_sync.py` — SCENE_GAP 0.4→0.5
- `video/evan_dynamic.py` — DEPRECATED 주석
- `renderer/shortform_renderer.py` — DEPRECATED 주석 + warnings.warn
- `remotion/render_bridge.py` — slides_to_scenes() DEPRECATED 주석
- `remotion/src/Root.tsx` — calculateMetadata 추가
- `remotion/src/compositions/ShortForm/index.tsx` — Audio 제거
- `remotion/src/animations/evanTiming.ts` — SCENE_GAP 추가
- `remotion/src/types/shortform.ts` — variant 필드 추가
- `remotion/src/scenes/HookScene.tsx` — 타이핑+아이콘+variant+글로우+Vignette
- `remotion/src/scenes/ChecklistScene.tsx` — 타이핑+CheckCircle+variant+틸트+Vignette
- `remotion/src/scenes/DataScene.tsx` — 타이핑+아이콘+easeOutExpo+variant+Vignette
- `remotion/src/scenes/InfoScene.tsx` — 타이핑+아이콘+틸트+variant+Vignette
- `remotion/src/scenes/CtaScene.tsx` — 타이핑+아이콘+variant+글로우+Vignette
- `video/tests/test_scene_composer.py` — variant 테스트 9건 추가

---

## 테스트 결과

**Python**: 62 passed, 1 warning (pydub audioop deprecation — 서드파티) in 0.25s
- test_pipeline_orchestrator.py: 21 passed
- test_scene_composer.py: 41 passed

**TypeScript**: `npx tsc --noEmit` exit code 0, 에러 0건

**pyright**: 0 errors, 0 warnings (프로젝트 루트에서 실행)

**black/isort**: All files formatted correctly

---

## 발견 이슈 및 해결

### 자체 해결 (3건)

1. **SCENE_GAP/transitionDuration 불일치** — Python SCENE_GAP 0.4→0.5로 수정, evanTiming.ts에 SCENE_GAP:15 추가
2. **타이핑 효과 미적용 (4개 Scene)** — ChecklistScene/DataScene/InfoScene/CtaScene 전체에 useTypingEffect 적용
3. **Unicode 문자 아이콘 사용** — lucide-react 설치 후 5개 Scene에 SVG 아이콘 교체/추가

### 범위 외 미해결 (2건)

1. **test_tts_sync.py pitch 테스트 실패** — 테스트가 pitch='+50Hz' 기대하지만 코드는 '+0Hz'. 본 작업과 무관한 기존 이슈. (범위 외: 기존 테스트 버그)
2. **CardNews.test.tsx THEMES 개수 실패** — 테스트가 5개 기대하지만 실제 7개 (EvanDark, Evan 추가됨). 본 작업과 무관한 기존 이슈. (범위 외: 이전 작업에서 테마 추가 시 테스트 미갱신)

⚠️ 기존 테스트 실패 2건 (본 작업 범위 외):
- `video/tests/test_tts_sync.py::TestGenerateNarration::test_generate_narration_creates_files`
- `remotion/src/__tests__/CardNews.test.tsx::Theme 타입 검증::THEMES 배열은 5개의 테마를 포함해야 한다`

---

## 에반 6원칙 준수 현황

1. ✅ 검정 배경: bg_gradient ["#0F0F0F", "#0F0F0F"] 유지
2. ✅ 테마 색상: accent/accent2 포인트 컬러 전장면 적용
3. ✅ 레이아웃 변주: 5개 Scene × 2 variant(A/B) = 10가지 레이아웃
4. ✅ 타이핑 효과: 전 장면 useTypingEffect 적용 완료
5. ✅ 시간차 등장: EVAN.ELEMENT_DELAY(24프레임) 기반 stagger
6. ✅ 다이나믹: 글로우/spring바운스/틸트/easeOutExpo/Vignette/그라데이션시프트

---

## 검증 기준 달성 현황

1. **파이프라인 E2E**: pipeline_orchestrator.py 구현 완료 (실제 렌더링은 Remotion+swap 인프라 필요)
2. **TTS-영상 싱크**: compose_scenes_with_durations()가 TTS 길이 기반 duration 설정
3. **에반 6원칙**: 6/6 충족
4. **아이콘 연계**: 5개 Scene 전체에서 lucide 아이콘 활용
5. **레이아웃 변형**: 5개 Scene × A/B variant 구현
6. **OOM 없이 렌더링**: gl=swangle + concurrency=1 기본 설정 (swap 설정은 sudo 필요)
7. **최종 MP4**: 1080x1920(9:16), 30fps 설정 유지

**미완료 항목**:
- Swap 4GB 설정 (sudo 권한 필요 — 인프라팀 요청 필요)
- 실제 E2E 렌더링 테스트 (Remotion CLI + Chromium 실행 필요)

---

## 인프라 참고사항

Swap 설정은 sudo 권한이 필요하므로 별도 인프라 작업으로 분리 권장:
```bash
sudo fallocate -l 4G /swapfile_remotion
sudo chmod 600 /swapfile_remotion
sudo mkswap /swapfile_remotion
sudo swapon /swapfile_remotion
# /etc/fstab에 영구 마운트 추가
```
