# make-youtube > 대본에서 TTS, SRT 자막, 스토리보드, 이미지를 자동 생성하는 유튜브 영상 제작 파이프라인. 유튜브/영상/TTS/자막/스토리보드/이미지 생성 관련 요청 시 사용. - Author: lbm1202 - Repository: nossidev/youtubeweb - Version: 20260206063249 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/nossidev/youtubeweb - Web: https://mule.run/skillshub/@@nossidev/youtubeweb~make-youtube:20260206063249 --- --- name: make-youtube description: 대본에서 TTS, SRT 자막, 스토리보드, 이미지를 자동 생성하는 유튜브 영상 제작 파이프라인. 유튜브/영상/TTS/자막/스토리보드/이미지 생성 관련 요청 시 사용. --- # 유튜브 영상 제작 대본에서 TTS, SRT 자막, 스토리보드, 이미지까지 자동 생성합니다. --- ## ⚠️ 핵심 원칙: 단계별 검증 + 승인 **모든 작업에서 반드시 준수할 것:** ### 1. Step 실행 전: SKILL.md 확인 - 각 Step 실행 전 **이 문서의 해당 섹션을 다시 읽는다** - 명령어, 인자, 출력 파일을 정확히 확인한 후 실행 ### 2. Step 완료 후: 출력 검증 - 출력 파일 존재 확인 (`ls` 또는 `Read`) - 파일 내용이 예상과 일치하는지 확인 (JSON 유효성, 필수 필드 등) - 에러 메시지가 있으면 즉시 보고 ### 3. Phase 완료 시: 유저 승인 요청 각 Phase 완료 후 **반드시 유저에게 결과 보고 + 승인 요청**: ``` ✅ Phase N 완료 [생성된 파일 목록] - file1.json (N개 항목) - file2.mp3 (M초) ... [검증 결과] - ✓ 파일 존재 확인 - ✓ 내용 유효성 확인 다음 Phase로 진행할까요? ``` ### 4. 승인 없이 다음 Phase 진행 금지 - 유저가 "진행", "ㅇㅇ", "네" 등 명시적 승인을 할 때까지 대기 - 문제 발견 시 수정 방법 제안 후 재승인 요청 --- ## 사전 확인: 채널 체크 영상 제작 전 `channels/` 디렉토리를 확인한다. 1. `channels/` 에 채널 디렉토리가 **하나도 없으면**: - "채널 설정이 필요합니다. `/setup-channel`로 먼저 채널을 만들어주세요." 안내 후 **중단** 2. 채널이 있으면: - 사용자가 채널을 지정했으면 → 해당 채널의 `config.md`, `image-style.md`, `split-prompt.md` 존재 확인 - 지정하지 않았으면 → 채널 목록 보여주고 선택 요청 - 필수 파일이 누락되면 → "채널 설정이 불완전합니다. `/setup-channel`로 보완해주세요." 안내 --- ## 입력: 대본 찾기 대본 위치: `input/{channel}/$PROJECT_NAME/new/{YYMMDD}_{제목}/script.txt` 사용자가 대본을 지정하지 않으면: 1. `input/{channel}/$PROJECT_NAME/new/` 폴더 스캔 2. 여러 개면 목록 보여주고 선택 요청 3. 하나면 바로 진행 4. **대본이 없으면** → `/write-script` 또는 `/draft-script`로 대본을 먼저 작성하라고 안내 후 **중단** --- ## 초기화: 설정 로드 ### 1. output 폴더 생성 ``` output/{channel}/$PROJECT_NAME/{YYMMDD}_{제목}/ ├── images/ # 최종 이미지 └── _intermediate/ # 중간 산출물 ``` **폴더명 결정:** - `{channel}`: 입력 대본의 채널명 (예: `input/my-channel/$PROJECT_NAME/new/...` → `my-channel`) - `$PROJECT_NAME`: 환경변수에서 읽은 프로젝트명 - `{YYMMDD}_{제목}`: 입력 폴더명 그대로 사용 (예: `250201_테스트제목`) ### 2. 설정 병합 → `_intermediate/settings.json` 저장 **우선순위**: 실행 시 요청 > 채널 설정 > config.yaml ### 3. 대본 전처리 → `_intermediate/script.txt` 저장 (아래 규칙 참고) ### 대본 전처리 규칙 input의 원본 대본에서 **본문만 추출**하여 `_intermediate/script.txt`에 저장: **제거 대상:** - 타임스탬프 (`[0:00-0:30]` 등) - 구분선 (`---`) - 섹션 제목 **형식:** - 본문 내용만 유지 (글자 하나도 바꾸지 않기) - **문단 단위로 개행 (단일 `\n`)** - 문단 내에서는 한 줄로 연결 - **연속된 개행(`\n\n`)은 단일 개행(`\n`)으로 압축** ## Phase 1: TTS + SRT 생성 ### Step 0: TTS 변환 (숫자/영어 → 한글) ```bash .venv/bin/python src/tts/extract_tts_targets.py {input_script} -o {output_dir}/_intermediate/tts_map.json ``` → [tts-conversion.md](tts-conversion.md) 참고하여 `tts_map.json`의 conversions 채우기(conversions 작성 규칙 확인 필수) ```bash .venv/bin/python src/tts/apply_tts_map.py {input_script} {output_dir}/_intermediate/tts_map.json -o {output_dir}/_intermediate/tts_script.txt ``` → `_intermediate/tts_script.txt` 생성 ### Step 1: TTS 생성 ```bash .venv/bin/python src/tts/generate_tts.py {output_dir}/_intermediate/tts_script.txt {output_dir} --config {output_dir}/_intermediate/settings.json ``` → `_intermediate/audio_raw.mp3`, `_intermediate/alignment.json` 생성 ### Step 2: SRT 생성 **2-1. Python:** 문장 분석 ```bash .venv/bin/python src/tts/analyze_sentences.py {output_dir}/_intermediate/alignment.json -o {output_dir}/_intermediate/sentences.json --config {output_dir}/_intermediate/settings.json ``` **2-1.5. Python:** tts_map에 sentence_idx 추가 ```bash .venv/bin/python src/tts/add_sentence_idx.py {output_dir}/_intermediate/tts_map.json {output_dir}/_intermediate/sentences.json ``` → `tts_map.json`에 `sentence_idx` 필드가 추가됨 **2-2. Python:** 청크 분할 ```bash .venv/bin/python src/tts/chunk_sentences.py {output_dir}/_intermediate/sentences_to_split.json -o {output_dir}/_intermediate ``` → `chunks/chunk_*.json` + `chunk_manifest.json` 생성 (0개면 chunk_count: 0) **2-3. Subagent:** 문장 분할 → [split-sentences.md](split-sentences.md) 참고 - `chunk_manifest.json` 읽고 청크 수만큼 Subagent 병렬 호출 - 각 Subagent: `chunk_N.json` → `split_part_N.json` **2-4. Python:** 결과 병합 ```bash .venv/bin/python src/tts/merge_splits.py {output_dir}/_intermediate/chunks -o {output_dir}/_intermediate/split.json ``` **2-5. Python:** SRT 생성 ```bash .venv/bin/python src/tts/create_srt.py {output_dir}/_intermediate/sentences.json -o {output_dir}/_intermediate/subtitle_raw.srt --split-data {output_dir}/_intermediate/split.json --tts-map {output_dir}/_intermediate/tts_map.json ``` ### Step 3: 무음 압축 ```bash .venv/bin/python src/tts/remove_silence.py {output_dir}/_intermediate/audio_raw.mp3 {output_dir}/_intermediate/subtitle_raw.srt {output_dir}/audio.mp3 {output_dir}/_intermediate/subtitle_trimmed.srt --config {output_dir}/_intermediate/settings.json ``` ### Step 4: 프레임 스냅 ```bash .venv/bin/python src/tts/align_to_frames.py {output_dir}/_intermediate/subtitle_trimmed.srt {output_dir}/subtitle.srt --config {output_dir}/_intermediate/settings.json ``` **TTS만 모드는 여기서 종료.** ### ✅ Phase 1 완료 체크포인트 **검증 항목:** 1. `_intermediate/tts_script.txt` - TTS 변환된 대본 2. `_intermediate/audio_raw.mp3` - 원본 TTS 음성 3. `_intermediate/alignment.json` - 문자별 타이밍 4. `_intermediate/sentences.json` - 문장 분석 결과 5. `_intermediate/split.json` - 문장 분할 결과 6. `_intermediate/subtitle_raw.srt` - 원본 자막 7. `audio.mp3` - 무음 압축된 최종 음성 8. `subtitle.srt` - 프레임 스냅된 최종 자막 **유저에게 보고:** - 총 문장 수, 자막 수, 음성 길이 - SRT 샘플 (처음 3개 자막) - "Phase 2로 진행할까요?" 승인 요청 --- ## Phase 2: 스토리보드 생성 ### Step 5: 스토리보드 생성 **5-1. SRT 파싱 (Python):** ```bash .venv/bin/python src/storyboard/parse_srt.py {output_dir}/subtitle.srt ``` → `_intermediate/subtitles.json` 생성 (자막 ID + 타임스탬프 + 텍스트) **5-2. 스토리보드 생성 (Claude):** [create-storyboard.md](create-storyboard.md) 참고 - 입력: `subtitles.json` 내용 - 출력: `_intermediate/storyboard.json` (subtitle_range만 있음) **5-3. 타임스탬프 매핑 (Python):** ```bash .venv/bin/python src/storyboard/map_timestamps.py {output_dir} ``` → `storyboard.json`에 `start`, `end` 필드 추가 (subtitle_range 기반으로 자동 계산) ### Step 6: 스토리보드 확인 - 스토리보드가 생성되면 웹앱의 프로젝트 상세 페이지에서 "스토리보드 보기" 버튼으로 확인 가능 - 웹앱 뷰어에서 자동 새로고침을 켜면 이미지 생성 진행상황 실시간 확인 가능 ### ✅ Phase 2 완료 체크포인트 **검증 항목:** 1. `_intermediate/subtitles.json` - 파싱된 자막 데이터 2. `_intermediate/storyboard.json` - 스토리보드 (scenes 배열 존재) - 각 씬에 `id`, `subtitle_range`, `description`, `prompt`, `start`, `end` 필드 **유저에게 보고:** - 총 씬 수 - 씬 목록 요약 (씬 번호 + 자막 범위) - "스토리보드 뷰어에서 확인 후 Phase 3로 진행할까요?" 승인 요청 --- ## Phase 3: 이미지 생성 ### Step 7: Whisk 이미지 생성 1. 환경변수 `WHISK_COOKIES`에서 쿠키 로드 (웹앱이 자동 설정) 2. 각 씬의 영어 프롬프트로 이미지 생성 ```bash .venv/bin/python src/image/generate_images.py {_intermediate/storyboard.json} ``` 3. images/ 폴더에 저장 4. `_intermediate/storyboard.json`에 image_path, status 업데이트 5. 뷰어에서 자동 새로고침으로 진행상황 실시간 확인 가능 ### Step 8: 이미지 검증 (선택) config.yaml의 `validation.enabled: true`인 경우: 1. [validate-image.md](validate-image.md) 참고하여 검증 2. threshold 미만이면 재생성 3. 최대 max_attempts까지 시도 ### ✅ Phase 3 완료 체크포인트 **검증 항목:** 1. `images/` 폴더에 씬 수만큼 이미지 파일 존재 2. `_intermediate/storyboard.json`의 각 씬에 `image_path`, `status` 필드 업데이트 **유저에게 보고:** - 생성된 이미지 수 / 총 씬 수 - 실패한 씬 목록 (있으면) - "스토리보드 뷰어에서 이미지 확인 후 Phase 4로 진행할까요?" 승인 요청 --- ## Phase 4: CapCut 프로젝트 생성 + 완료 ### Step 9: CapCut 프로젝트 생성 1. MP3 + SRT + 이미지를 CapCut 프로젝트로 변환 + ZIP 생성 ```bash .venv/bin/python src/capcut/generate_capcut.py {output_dir} --name {project_name} --zip ``` 2. `capcut_project.zip` 파일이 output 디렉토리에 생성됨 3. 웹앱에서 다운로드 가능 ### Step 10: 대본 아카이브 + 결과 요약 1. 입력 대본 폴더를 archive로 이동 ```bash mv input/{channel}/$PROJECT_NAME/new/{YYMMDD_HHMM}_{제목} input/{channel}/$PROJECT_NAME/archive/ ``` 2. 결과 요약 출력: - output 경로 - CapCut 프로젝트 다운로드 (웹앱) - "대본이 archive로 이동됨" 안내 --- ## 이미지 재생성 모드 기존 output 폴더에서 특정 씬의 이미지만 재생성. **상세 가이드:** [image-regeneration.md](image-regeneration.md) ``` "씬 3, 5 이미지 다시 만들어줘" "실패한 이미지만 재생성해줘" "씬 3이 너무 어두워요. 더 밝게 해주세요" ``` ### 주요 옵션 - 특정 씬 / 실패한 씬 / 점수 미달 씬 / 전체 - `--keep-original`: 원본 유지하고 새 버전 추가 - `--variations N`: 변형 N개 생성 - 프롬프트 수정 후 재생성 --- ## 병렬 처리 모드 여러 대본을 한번에 처리. **상세 가이드:** [parallel-processing.md](parallel-processing.md) ``` "input/my-channel 폴더의 대본들 다 처리해줘" "대본1, 대본2, 대본3 한번에 만들어줘" ``` ### 전략 - TTS 단계: 순차 처리 (ElevenLabs rate limit) - 이미지 단계: 병렬 처리 (여러 계정 활용) - 진행 상황 실시간 표시 - 실패한 대본만 스킵, 나머지 계속 진행 --- ## 출력 구조 ``` output/{channel}/$PROJECT_NAME/{YYMMDD_HHMM}_{제목}/ ├── audio.mp3 # 최종 MP3 (무음 압축됨) ├── subtitle.srt # 최종 SRT (프레임 스냅됨) ├── capcut_project.zip # CapCut 프로젝트 (웹 다운로드용) ├── images/ # 최종 이미지 │ ├── scene_001.png │ └── ... └── _intermediate/ # 중간 산출물 ├── script.txt # 원본 대본 (복사본) ├── tts_script.txt # TTS용 대본 (숫자 변환됨) ├── storyboard.json # 스토리보드 ├── audio_raw.mp3 # 원본 TTS ├── alignment.json # TTS 타이밍 ├── sentences.json # 문장 분석 (전체, Python용) ├── sentences_to_split.json # 분할 필요 문장 (Claude용) ├── split.json # 분할 정보 ├── tts_map.json # TTS 변환 매핑 ├── subtitle_raw.srt # 원본 자막 ├── subtitle_trimmed.srt # 무음압축 후 자막 └── settings.json # 설정 ``` --- ## 에러 처리 ### API 실패 - **ElevenLabs 크레딧 부족**: 필요 글자 수와 남은 크레딧 표시 후 중단 - **Whisk 쿠키 만료**: "쿠키 갱신 필요" 알림 - **Whisk 정책 위반**: 해당 씬 스킵, 프롬프트 수정 필요 표시 ### 중단 후 재시작 - storyboard.json에 상태 저장됨 - 재실행 시 "이어서 할까요?" 확인 - pending 상태인 씬만 처리