기술 강연 비디오
세 단계로 구성되며, 각 단계마다 사용자가 명확히 "좋아"라고 말해야 다음 단계로 넘어갑니다. 사용자 전역 설정의 "확인 없이 바로 실행"은 이 세 단계에 적용되지 않습니다. 이는 사용자가 이 스킬을 위해 특별히 요청한 검토 프로세스입니다. 사용자가 "아직 더빙하지 마/아직 하지 마"라고 말하면 현재 단계에서 멈춥니다.
기본값 (사용자가 언급하지 않으면 이 값을 따르고, script.md의 front matter에 기록):
- 대상 청중: Python을 할 줄 알지만, 관련 과정은 거의 다 잊어버린 대학생. 작성 방식은
references/kepu-style.md를 따릅니다: 구체적인 것에서 추상적인 것으로, "여러분이 직접 설계한다면", 한 장의 물리적 그림이 전체 영상을 관통하며, 각 에피소드당 새로운 용어는 6개를 넘지 않습니다; 레지스터, 소스 코드 수준의 세부 사항은 각 에피소드 끝의 "심화" 장에 배치합니다. - 목표: 시청 후 PyTorch로 직접 작성할 수 있을 정도
- 구조: 세 부분, 수학 원리 → 사용할 PyTorch 도구 → 통합 코딩
- 각 에피소드 내부는 "총체—분할—총체" 구조: 시작 부분에 이 에피소드가 답할 질문과 섹션 지도를 먼저 제시하고, 본문에서 섹션별로 전개하며 (화면 모서리에 경로 지도 표시, 현재 섹션 강조), 끝 부분에서 각 섹션을 한 문장으로 요약하고 다음 에피소드를 예고합니다.
- 길이: 각 에피소드 8–12분 (2026-10-24 사용자 변경: 에피소드 수 적음, 게시물 적음, 플랫폼 한도에 쉽게 부딪히지 않음), 하나의 주제는 보통 2개 에피소드, 최대 3개 에피소드
- 비유: 허용되지만, 한 가지 점만 설명: 한 문장으로 비유를 마치고 바로 본론으로 돌아가며, 하나의 개념에 최대 하나의 비유만 (kepu-style.md 항목 5)
- 음색:
voice: volc(火山引擎(Volcano Engine) 프리셋 음색 zh_female_vv_uranus_bigtts);~/.volc_tts.env에 자격 증명이 없으면 tts.py가 자동으로 edge-tts 晓伊로 대체하고 안내 메시지를 출력합니다.
단계 0: 자료 수집
사용자가 노트(예: Obsidian)를 언급하면 먼저 찾아서 정독하고, 노트의 구조, 결론 및 숫자를 기준으로 삼습니다.
단계 1: 아웃라인 (대화에서 제공)
첫 줄에 한 문장으로 프로젝트 목표를 작성합니다: "이번 에피소드는 X를 하는 사람이 Y를 할 수 있게 만든다." 각 에피소드에 대해 커버 후크 + 오른쪽 시각 자료 한 줄 (자세한 내용은 references/cover-guide.md 참조)을 아웃라인과 함께 검토합니다.
references/outline-template.md에 따라 간단한 표를 작성합니다: 각 장에서 해결할 문제, 새로운 개념, 구현할 코드, 길이, 그리고 에피소드 분할 계획 및 다루지 않을 내용.
먼저 references/kepu-style.md를 읽습니다. 시작, 리듬, 용어 및 끝부분은 references/script-guide.md의 "시작 공식", "리듬", "용어 및 난이도", "끝맺음 공식"에 따라 설계합니다; 아웃라인에서는 각 하이라이트 포인트가 어느 장에 있는지만 표시합니다.
수학 부분을 작성할 때는 먼저 계산할 목표(예: out_i = Σⱼ aᵢⱼ vⱼ)를 제시한 다음 각 구성 요소를 도출하여, 내적(dot product), softmax, 스케일링이 "필요해서 등장"하도록 만듭니다.
단계 2: 코드 → 대본 → 검사 → 주석 → 최종 확정
대본 작성 원칙: 먼저 설계 동기를 설명하고, 그 다음 메커니즘, 마지막으로 결과를 설명합니다. "원래 어떤 문제가 있었는가 → 설계자가 무엇을 해결하려 했는가 → 왜 이 방법을 선택했는가 → 어떻게 작동하는가"를 우선적으로 명확히 설명합니다. 단계, 예시 및 필요한 정확성을 추가하는 것은 허용되지만, 현재 원리를 이해하는 데 꼭 필요한 새로운 개념만을 도입합니다; 새로운 용어가 처음 등장할 때는 기존 지식이나 구체적인 예시를 사용하여 설명합니다. 심화 장은 해당 장의 사전 설정된 지식 기반에 맞춰 조정합니다.
- 튜토리얼 코드
py/tutorial.py를 작성하고 실제로 실행하며,show(key, value)를 사용하여py/values.json을 내보냅니다. 화면의 모든 숫자, 형태, True/False는 여기에서 가져옵니다.- 작은 예제가 설명 가능한 의미를 가질 때는 수동으로 가중치를 설정하고, 코드 주석과 나레이션에 "수동 설정, 실제 모델은 학습에 의존"이라고 설명합니다.
- "왜"를 설명할 때는 실제 대조군을 사용합니다: 예를 들어 결합 법칙의 softmax 유무에 따른 allclose, 스케일링 전후 softmax Jacobian 노름 등.
references/kepu-style.md및references/script-guide.md에 따라script/script.md를 작성하고(형식은 아래 참조), 두 개의 자체 점검 목록을 한 번씩 확인합니다. 각 "화면:" 문장은 시청자가 보게 될 변화와 이 그림이 이해에 어떻게 도움이 되는지를 명확하게 작성합니다; 먼저 표현 목표를 결정하고, 제작 도구는 고정하지 않습니다. 화면은 웹 캔버스, Remotion, Manim, Blender 또는 더 적합한 도구를 사용하여 구현할 수 있으며, 구체적인 선택은 최종 확정 후 샷(shot)별로 이루어집니다. 숫자, 코드 또는 형태가 포함된 화면은 여전히py/values.json,py/tutorial.py와 일치해야 합니다. 에피소드 핵심 길이 확인: 각 에피소드 번호 줄의 글자 수 ÷ 4.5 ÷ 60, 여기에 약 0.5분의 장 카드 및 일시 정지를 더했을 때 12분을 초과하면 이 단계에서 에피소드 분할을 조정합니다 (더빙 완료 후에야 너무 길다는 것을 발견하지 않도록 합니다).- 초고 완성 후, 순서대로 기초 지식 검사, 사실 확인 및 언어 다듬기를 수행합니다:
3b. 기초 지식 진입 장벽 검사 (필수): 다른 agent를 시작하고, 오직 script.md와 "Python을 할 줄 알지만, 이 주제에 대한 수업은 거의 다 잊어버렸다"는 설정만 제공합니다.
코드나 노트는 제공하지 않습니다. 각 문장을 하나씩 표시하도록 합니다: ① 이해할 수 없는 단어 또는 추론 과정 생략; ② 한 문장에 너무 많은 새로운 내용이 도입되어 다시 돌아가 봐야 하는 부분; ③ 화면 설명과 나레이션이 일치하지 않는 부분.
구체적으로 어느 단계의 설명이 누락되었는지 지적하도록 요구하며, 특히 "문제 → 설계 동기 → 메커니즘 → 결과" 순서로 이해할 수 있는지 확인합니다. 단계, 예시 또는 필요한 정확성을 추가하도록 제안할 수 있지만, 세부 사항을 추가하기 위해 본선과 관련 없는 새로운 개념을 도입하지 않아야 합니다. 수정 사항을 하나씩 반영한 후, 동일한 조건으로 다시 검사하여 ①, ② 유형의 표시가 없을 때까지 반복합니다. ③ 유형도 수정해야 합니다. 수정 목록을 기록하여 배포 시 사용자에게 함께 제공합니다. 심화 장은 해당 장의 사전 설정된 지식 기반에 따라 검사합니다.
3c. 사실 확인 (필수): 다른 agent를 시작하고, script.md와 노트를 제공하며, 사실 오류 또는 오해를 불러일으킬 수 있는 진술만 표시하고 그 근거를 설명하도록 합니다; 지식 포인트, 경계 조건 또는 추가 세부 사항의 보충은 요구하지 않습니다. 교육적 단순화는 허용됩니다; 시청자가 단순화된 표현을 엄격한 정의로 오해할 가능성이 있으면 나레이션에서 "여기서는 단순화했습니다"라고 간략히 설명합니다. 수정 시에는 동일하게 간단하지만 정확한 표현을 우선적으로 선택하고, 제한 수식어를 쌓지 않습니다. 3b와 충돌하는 경우, 정확하면서도 이해하기 쉬운 표현을 찾습니다; 사실 오류를 유지할 수 없으며, 정확성이 설명의 본선을 압도하지 않도록 해야 합니다. 사실 수정이 이해나 화면에 영향을 미치는 경우, 해당 3b 검사를 다시 수행합니다.
3d.
humanizer-zh스킬을 사용하여 번호 줄과 "읽기:" 줄을 문장별로 다듬습니다 (AI 감 제거). 숫자, 용어, 코드 및 "화면:" 줄의 의미는 유지하고, 함부로 지식 포인트를 추가하거나 삭제하지 않습니다. 다듬은 후 코드 결과, 화면 설명 및 나레이션이 일관되는지 다시 확인하고, 각 에피소드의 길이를 다시 계산합니다. - 파일을 사용자에게 보내고(SendUserFile), 문장 아래에
>로 시작하는 주석을 작성하도록 요청합니다 (Obsidian의> [!주석]도 가능). Obsidian에서 주석을 작성하려면 사용자 vault로 복사하고, 수정한 후 다시 읽어옵니다. - 주석 처리: 하나씩 수정 → 처리된 주석 줄 삭제 → 대화에서 각각 어떻게 수정했는지 나열 → 사용자에게 다시 확인 요청, 사용자가 최종 확정했다고 말할 때까지 반복합니다.
- 최종 확정 전에는 더빙하지 않고, 공식 화면을 제작하지 않습니다. 복잡한 샷의 구현 가능성을 검증하기 위해 짧은 데모를 만들 수 있습니다; 데모는 대본 검토를 대체하지 않습니다.
script.md 형식
---
title: Attention → MHA → GQA
subtitle: 수학 원리에서 PyTorch 구현까지
audience: 기초 컴퓨터 지식을 갖춘 대학생
voice: volc
volc_speaker: zh_female_vv_uranus_bigtts
volc_resource: seed-tts-2.0
episodes: ch0,ch1,ch2,ep1_end | ep2_start,ch3,ch4,ep2_end | ep3_start,ch5,ch6
episode_titles: 첫 번째 에피소드 제목 | 두 번째 에피소드 제목 | 세 번째 에피소드 제목
---
## ch0 | 오프닝
1. 자막 원문, 한 문장에 하나의 화면 박자.
- 읽기: TTS 발음 방법 (자막과 다를 때만 작성; 기호는 발음으로 작성, '行'(háng)은 "항"으로 작성)
- 화면: 이 문장에서 화면에 나타나는 내용 (필수, 화면 agent가 이를 보고 구현)
> 주석: 사용자가 여기에 작성
## ep1_end | 다음 에피소드 예고
1. 다음 에피소드에서는……
- 화면: EP1 종료 카드
- 장 id:
ch0, ch1, …; 에피소드의 오프닝/엔딩은epK_start/epK_end를 사용하며, 화면은 공통 EpCard로 자동 생성됩니다. 새로 추가된 문장도 사용자 검토를 받아야 합니다. - 총체-분할-총체:
epK_start는 2–3문장: ① 이 에피소드가 답할 질문 ② "이 에피소드는 N가지를 다룹니다: ……" (에피소드의 장과 일대일 대응);epK_end는 2–3문장: 각 장당 한 문장 결론 + 다음 에피소드 예고. 첫 번째 에피소드의 오프닝 장(ch0)도 에피소드 지도를 포함해야 합니다. front matter의episodes는 지도에 포함될 섹션을 결정하며, 섹션 이름은 각 장의 제목에서 가져옵니다. - 자막을 수동으로 짧게 나눌 필요가 없습니다. tts.py가 구두점을 기준으로 ≤22자 너비의 짧은 조각으로 나눕니다.
단계 3: 비디오 생성
샷별로 원리를 명확히 설명할 수 있는 제작 방식을 선택합니다: 2D 관계, 코드 및 데이터는 웹 캔버스, Remotion 또는 Manim을 사용할 수 있습니다; 공간 구조 및 카메라 움직임은 Blender와 같은 3D 도구를 사용할 수 있습니다. 더 적합한 새 도구를 사용할 수도 있으며, 특정 도구를 사용하기 위해 설명의 복잡성을 증가시키지 않아야 합니다. 기존 template/은 Remotion 합성 및 전달 파이프라인입니다; 다른 도구로 제작된 샷은 먼저 비디오 또는 이미지 자료를 출력하고, 해당 파이프라인에 통합되어 자막, 더빙, 박자 동기화를 유지할 수 있는지 확인한 후 공식 장에 사용합니다. references/visual-guide.md 및 references/agent-brief.md의 구성 요소, 경로 및 명령은 Remotion 장에만 적용되며, 다른 도구는 자체 레이아웃, 색상, 실제 데이터 및 화면 자체 검사 원칙을 따릅니다.
template/을 사용자가 지정한 디렉토리(기본값~/Videos/<주제>, 먼저 물어보기)에 복사하고,py/,script/를 넣습니다. 의존성은 한 번만 설치: 시리즈(여러 프로젝트가 동일한 부모 디렉토리, 예:~/Videos/nudgecode-알고리즘/<장>/에 있음)인 경우 부모 디렉토리에 한 번만node_modules를 설치하고(template의 package.json을 복사하여npm install실행), 각 프로젝트는ln -s ../node_modules node_modules로 심볼릭 링크를 겁니다; 단일 프로젝트라면 프로젝트 내에 설치합니다.npm install은 동시에 하나만 실행하며, 동시 실행은 패키지를 망가뜨릴 수 있습니다. 설치 후node_modules/react-dom/index.js가 존재하는지 확인합니다 (npm 캐시에서 이 패키지가 손상된 적이 있으므로, 파일이 없으면 다른 프로젝트에서 동일 버전을 복사합니다).python3 tools/md2json.py(처리되지 않은 주석이 있으면 거부함) →python3 tools/scaffold.py→python3 tools/tts.pypublic/audio/*,src/timeline.json을 생성하며, 더빙은 캐시되어 수정된 문장만 다시 합성합니다.- 먼저 오프닝과 첫 번째 장을 직접 제작하여 화풍을 확립합니다 (가장 어려운 샷을 먼저 제작; 리듬 및 전환은
references/plotome-lessons.md참조). Remotion 샷은node tools/stills.mjs ch1 && tools/sheet.sh ch1로 확인합니다; 외부 도구로 제작된 샷은 원본 자료 및 통합 후 합성 프레임을 확인하고, 미리보기를 사용자에게 보냅니다. 시리즈에서 화풍이 이미 사용자에게 확인된 경우(예: 동일 시리즈의 첫 번째 프로젝트), 별도로 사용자에게 보여주지 않고 계속 진행합니다.stills.mjs는out/bundle을 재사용합니다 (tools/bundle.mjs로 번들링하며, 소스 파일이 변경된 경우에만 다시 패키징), 매번$TMPDIR에 약 90MB의 번들 디렉토리를 새로 만들지 않습니다. - 사용자가 승인하면, 나머지 장을 여러 agent에 한 번의 메시지로 동시에 시작합니다 (각각 1–2장):
- Remotion 장:
references/agent-brief.md를 채워 프로젝트 루트 디렉토리의AGENT_BRIEF.md로 작성하고,references/visual-guide.md를VISUAL_GUIDE.md로 복사합니다. 외부 도구 샷은 별도로 간단한 작업 설명을 작성하고, 자료 형식, 길이, 파일 위치 및 Remotion 통합 책임을 약속하며,ChN.tsx만 수정하도록 제한하는 규칙을 적용하지 않습니다. - 나레이션이 변경되면 관련 agent에 SendMessage를 보내어 어떤 문장이 변경되었고 타임라인이 업데이트되었는지 설명합니다.
- Remotion 장:
- 모든 장이 도착하면, 메인 세션에서 장별로 합성 프레임을 검사합니다: 중첩, 자막 압박, 화면과 "화면:"의 일치 여부, 숫자가 values.json에서 왔는지 확인; 외부 자료는 가져온 후 길이와 박자를 추가로 확인합니다.
npx tsc통과 후, 백그라운드에서tools/render.sh를 실행합니다: 에피소드별로out/epK.mp4+out/epK.srt+out/covers/epK.jpg를 출력하고, -16 LUFS로 표준화합니다. 비디오 1분당 약 1분의 렌더링 시간이 소요됩니다. 렌더링 중에는 오디오와 코드를 건드리지 마십시오: 믹싱은 마지막 단계에서야 오디오를 읽으므로, 중간에 덮어쓰면 새 오디오와 기존 오디오가 섞입니다. render.sh는 전역 잠금(lockf /tmp/remotion-render.lock)을 사용하여 동시에 하나의 에피소드만 렌더링하도록 보장합니다: 여러 프로젝트를 동시에 렌더링해도 더 빠르지 않으며 (CPU가 이미 가득 참), 메모리와 디스크만 더 많이 사용합니다. 여러 프로젝트에서 동시에 render.sh를 시작할 수 있으며, 자동으로 대기열에 들어갑니다.- 커버:
references/cover-guide.md에 따라 각 에피소드별로src/covers/CoverEpK.tsx를 작성하고src/covers/index.ts에 등록합니다 (검은 배경, 후크 큰 글자 + 노란 배경 강조, 오른쪽 큰 시각 자료); render.sh가 자동으로out/covers/epK.jpg를 출력하며, 등록되지 않은 에피소드는 기본 버전을 사용합니다. 모든 커버를 하나의 이미지로 합쳐 사용자에게 보여줍니다. 개별 재출력:npx remotion still out/bundle cover-epK out/covers/epK.jpg. - 전달: SendUserFile을 사용하여 각 에피소드의 mp4, srt, 커버 및
py/tutorial.py를 보냅니다. 사용자가 직접 srt를 한 번 읽어보도록 요청하면 종종 문제를 발견할 수 있습니다. - 게시가 필요하면
video-publish스킬로 전환합니다. 게시 전에references/plotome-lessons.md의 규정 준수 체크리스트(AI 표시, 음악 라이선스, 저작자 표시)를 한 번 확인합니다.
시리즈 배치 제작 (여러 프로젝트 병렬)
- 동시에 열리는 세션은 3–4개로 제어합니다: 너무 많이 열면 곧 사용량 한도에 도달하고, Volcano TTS도 동시 실행 제한을 보고합니다 (tts.py는 이미 백오프 재시도, 동시 실행 2를 포함).
- 병렬 처리는 대본 작성과 화면 제작에만 사용하고, 렌더링은 render.sh의 전역 잠금에 맡겨 대기열에 넣습니다.
- 디스크: 각 장의
out/bundle은 약 90MB, 스크린샷out/check는 수십 MB, 완성본은 각 에피소드당 약 10MB입니다. 새 배치를 시작하기 전에df -h를 확인하고,$TMPDIR/remotion-webpack-bundle-*는 이전 버전 스크립트에서 남은 임시 번들로 정리할 수 있습니다. - 사용자가 "한 배치 렌더링 → 바로 업로드 → 완성본 삭제"에 동의한 경우,
video-publish의 "배치 파이프라인"을 참조하십시오.
메인 세션 스케줄링 파이프라인 (지식 베이스 2026-10-30 ~ 11-03에 검증됨, 두 편씩 한 배치)
- 대본 작성 단계 agent (각 편마다 하나씩, 두 편 동시에): 아웃라인 → tutorial 실제 실행하여 values.json 내보내기 → 대본 → 기초 지식 검사 (다른 agent 시작, 최대 8라운드, 이후 마지막 라운드를 기준으로 전체 수정) → 사실 확인 (다른 agent가 노트를 참조하여 확인) → humanizer → 에피소드 핵심 길이 확인 → template 복사, node_modules 심볼릭 링크 → md2json / scaffold / tts → AGENT_BRIEF.md, VISUAL_GUIDE.md, 공유 물리적 그림 구성 요소
src/lib/<이름>.tsx작성 (먼저 레이아웃 상수 결정) → ch0, ch1 제작. 보고서에는 "노트와 실제 측정 불일치 사항"을 나열해야 합니다. - 메인 세션이 ch0/ch1 콜라주를 보고, 화풍에 문제가 없으면 사용자를 기다리지 않고 계속 진행합니다.
- 화면 fan-out:
references/agent-brief.md를 채워 하나의 공유 brief로 작성하여/tmp/claude-501/brief_<편>.txt에 씁니다 (두 번째 편은 sed를 사용하여 경로/구성 요소 이름/잠금 이름을 바꾼 후 "이 프로젝트의 추가 사항"을 추가합니다). 각 agent의 프롬프트는 "먼저 Read로 brief를 완전히 읽고 엄격히 따르십시오. 당신은 chX, chY를 담당합니다"라는 한 문장만 있으며, 각각 2–3장이고 커버는 마지막 agent가 담당합니다. 한 번의 메시지로 동시에 시작합니다. - 알려진 문제 수집: 각 화면 agent가 돌아올 때, 그것이 보고한 "알려진 문제 / values.json에 없는 숫자 / 수정 후 재확인 안 함"을 기록합니다.
- 전체 영상 검토 agent (각 편마다 하나씩, 템플릿
references/review-brief.md): 4단계에서 수집된 문제를 하나씩 "알려진 수정 사항"에 작성합니다. - 렌더링: 두 편은 각각 백그라운드에서
tools/render.sh를 시작하며, 전역 잠금이 자동으로 대기열에 넣습니다; 하나의 백그라운드 until 루프를 사용하여out/ep3.mp4가 나타날 때까지 기다립니다. - 무작위 검사 (메인 세션이 직접 수행, 보고서 신뢰하지 않음): 각 에피소드
ffmpeg -af volumedetect(정상 mean 약 −19 dB, max ≤ −1.2 dB); 각 편에서 한 에피소드를 선택하여-vf "fps=1/60,scale=480:-1,tile=4x3"로 하나의 그리드 이미지를 만들고 Read로 확인합니다;out/covers/에 세 장이 모두 있는지 확인합니다. - 업로드:
out/parts/P<k> <후크>:<주제>.mp4하드 링크 +out/upload_meta.md(간략한 소개 추가 문단 포함)를 만든 후,video-publish의 "기존 원고에 추가"에 따라 대기열에 넣습니다. 업로드가 완료되면 PROGRESS.md와 칸반 보드를 업데이트하고, 소개 문단을 사용자에게 보냅니다.
사용량 한도 도달 / 중단
- 사용량 한도에 도달하면 실행 중인 모든 agent가 종료됩니다. 복구 후 SendMessage를 사용하여 각 agent에 "계속"을 보내면, 컨텍스트를 유지한 채로 이어서 작업합니다; 새 agent를 시작하지 마십시오 (중복 작업 및 서로 덮어쓰기 발생).
- 동시에 실행 중인 agent는 ~12개 이내로 제어합니다 (두 편 × 5–6개 화면 agent).
노트와 실제 측정 불일치
- 지식 베이스 노트(vault)는 읽기 전용입니다. 실제 측정과 노트가 일치하지 않을 때는 비디오가 실제 측정을 기준으로 설명하고, 보고서에서 하나씩 사용자에게 나열하여 사용자가 노트를 수정할지 여부를 결정하도록 합니다.
최종 확정 후 변경
- 나레이션 변경: script.md 수정 → md2json → tts (수정된 문장만 다시 합성) → 영향을 받는 장의 화면 확인.
- 문장 수가 변경되면 화면이 어긋날 수 있습니다: 이미 화면이 제작된 장은 가능한 한 표현만 수정하고 문장을 추가하거나 삭제하지 않습니다; 내용을 추가해야 한다면 새로운 한 문장 장(예: epK_start)으로 추가합니다.
- 화면 agent는
visual만 구현하고, 의문이 있으면 메인 세션에 보고하며, 자체적으로 나레이션을 수정하지 않습니다.
음색
- 火山引擎(Volcano Engine) 프리셋 음색 (기본값,
voice: volc):zh_female_vv_uranus_bigtts, 리소스seed-tts-2.0. GQA 에피소드에서 사용자가 선택했으며, 효과가 edge-tts보다 훨씬 좋습니다. front matter에volc_speaker를 명시하지 않으면 이 음색을 사용합니다. 자격 증명은~/.volc_tts.env(이미 설정됨)에 있으며,VOLC_APPID/VOLC_TOKEN만 필요합니다; 선택적으로VOLC_SPEED말하기 속도(1.0 기본)를 설정할 수 있습니다. - 음색 변경: front matter에
volc_speaker: <음색 ID>를 작성합니다. 프리셋 음색은 자동으로seed-tts-2.0을 사용합니다;S_로 시작하는 복제 음색은 자동으로seed-icl-2.0(또는 env의VOLC_RESOURCE)을 사용합니다.volc_resource를 사용하여 명시적으로 지정할 수도 있습니다;v1을 작성하면 이전 버전 인터페이스를 사용하며, 이때VOLC_CLUSTER(기본값 volcano_icl)를 추가로 설정할 수 있습니다. - 사용자의 복제 음색(env의
VOLC_SPEAKER_ID, S_로 시작)은 현재resource ID is mismatched with speaker오류를 보고하므로, 먼저 Volcano 콘솔에서 음색 버전, 훈련 상태, 소속 appid를 확인하고 성공적으로 실행될 때까지 사용하지 마십시오. - env 파일 내용을 출력하지 마십시오. 새 프로젝트는 먼저
--only를 사용하여 한 에피소드의 몇 문장을 합성하여 들어본 후 전체 영상에 적용합니다. - edge-tts (대체):
voice: zh-CN-XiaoyiNeural, 기타 옵션 YunxiNeural, YunyangNeural, XiaoxiaoNeural. Volcano 자격 증명이 없으면 tts.py가 자동으로 晓伊를 사용합니다. - 음색 변경은 tts.py만 다시 실행하면 되며, 화면은 박자에 따라 자동으로 정렬되므로 무작위 검사 콜라주만 확인하면 됩니다.
영어 더빙 (2026-11-03)
- edge-tts
en-US-AndrewMultilingualNeural: 사용자가 9개의 음색을 들어본 후 선택했습니다. 무료이며 키가 필요 없지만, Edge TTS의 비공식 인터페이스를 사용합니다: 속도 제한/연결 끊김이 발생할 수 있으며(tts 재시도 필요), 상업적 사용이 명확하지 않고 인터페이스가 변경되면 교체해야 합니다. front mattervoice: en-US-AndrewMultilingualNeural. - Volcano
seed-tts-2.0의en_male_tim_uranus_bigtts,en_female_dacey_uranus_bigtts사용 가능 (대체);seed-tts-1.0의*_mars_bigtts영어 음색은 이 계정에서 403 오류(미개통). 중국어 음색 vv도 영어를 읽을 수 있지만, 억양이 뚜렷합니다. - 듣기 평가: 동일한 약 20초 영어 오프닝 멘트를 각 음색별로 mp3로 출력한 후, ffmpeg concat(각각 뒤에 apad 1.2초)을 사용하여 하나의 컬렉션으로 합쳐 사용자에게 보냅니다.
중영 이중 언어 (시범 중)
- 시범 프로젝트
~/Videos/지식베이스/llm-13-rag-agent-en: 새로 작성된 영어 구어체 나레이션 (중국어를 영어로 번역한 것이 아님), 각 문장에 중국어 번역이 포함되며, 하단 두 줄 자막 (위 영어, 아래 중국어 약간 작게), 화면 라벨은 영어. - 자막 구성 요소와 md2json의 구체적인 변경 사항은 시범이 끝난 후 여기와 template에 다시 기록합니다.
- 영어 버전을 중국어 컬렉션에 추가하지 마십시오; 게시 대상(Bilibili 새 원고 / YouTube)은 사용자가 결정합니다.
파일 목록 (template/)
| 파일 | 역할 |
|---|---|
tools/md2json.py | script.md → script.json (주석 확인, 에피소드 분할 구문 분석) |
tools/scaffold.py | 장 자리 표시 구성 요소 및 src/chapters/index.ts 생성 |
tools/tts.py | 문장별 더빙, 짧은 자막 분할, timeline.json 작성; edge-tts / Volcano Engine 지원 |
tools/stills.mjs + sheet.sh | 각 문장의 80% 지점에서 스크린샷을 찍어 3×3 콜라주 생성 (SCALE=1은 전체 크기) |
tools/render.sh | 에피소드별 렌더링 + 자막 병합 + 음량 표준화 |
src/lib/beat.tsx | 박자 동기화 (useBeat), 장 제목 카드, 자막 |
src/lib/ui.tsx | CodePanel / Matrix / Fade / Tag / H / Tex (KaTeX 수식) |
src/lib/EpCard.tsx | 에피소드 오프닝/엔딩 카드 |
src/lib/Cover.tsx + src/covers/ | 커버 구성 요소 (CoverFrame / Hl / CodeVisual / BigNumber) + 각 에피소드 맞춤형 커버 등록 |
src/lib/algo.tsx | 알고리즘 클래스 구성 요소: 배열 그리드, dict, 추적 테이블, 문제 카드 |
tools/bundle.mjs | 한 번 번들링하여 out/bundle 재사용 |
src/lib/library.tsx | 선택 사항: 텐서 "도서관" 비유 구성 요소 (Building / Corridor) |
참조 문서
references/script-guide.md: 대본 작성법;outline-template.md: 아웃라인 표references/visual-guide.md/agent-brief.md: 화면 규격, 화면 agent 설명references/cover-guide.md: 커버 규격references/plotome-lessons.md: 리듬, 전환, 음악, 규정 준수 (plotome 참조)references/production-retro-2026-10.md: nudgecode 13장 배치 제작 회고, 문제점 및 대책references/production-retro-2026-11.md: 지식 베이스 두 편씩 한 배치의 스케줄링 파이프라인 회고references/review-brief.md: 전체 영상 검토 agent 템플릿rethinkfun-style.md/cishoon-style.md: 사용자가 좋아하는 유튜버 분석
경험한 문제점
- macOS
say는 너무 기계적이므로 edge-tts를 사용합니다. - 코드와 기호는 "읽기:"에서 발음 방식으로 작성해야 합니다; 다의어 '行'(háng)은 "항"으로 작성합니다.
- 실제 모델의 숫자를 설명하기 전에 해당 구조를 확인해야 합니다 (예: Llama-2-70B 자체가 GQA이고 64헤드 기준 10GB를 계산하려면 "MHA를 가정한다"고 말해야 함).
- 무작위 초기화된 어텐션은 너무 평균적이어서 의미가 없습니다: 수동으로 가중치를 설정하거나 무작위 시드를 변경하여 대비가 뚜렷한 것을 선택합니다.
- 스크린샷은
tools/stills.mjs를 사용하고 (한 번만 번들링),remotion still보다 훨씬 빠릅니다; 첫 번째 렌더링에서는 headless Chrome을 다운로드합니다. - Bash에서 입력이 없는
cat > file을 작성하지 마십시오. stdin을 영원히 기다리며 멈춥니다. - 스크린샷은 각 문장의 80% 지점에서 촬영: 80% 이후에 나타나는 애니메이션(빨간 X, 늦게 나타나는 큰 글자)은 캡처되지 않으므로 별도로 캡처하거나 표시 시간을 앞당겨야 합니다.
- 화면 agent가 병렬로 실행될 때, 다른 사람의 장에 구문 오류가 있으면 번들이 실패할 수 있습니다: 1-2분 기다렸다가 재시도하고, 다른 사람의 파일을 수정하지 마십시오.
- 검토 agent가 이전 스크린샷을 "정리"한 적이 있습니다: brief에 "어떤 파일도 삭제하지 않음 (스크린샷 덮어쓰기는 허용)"이라고 반드시 작성해야 합니다.
- 디스크: 각 편 프로젝트는 약 0.5GB, 완성본은 각 에피소드당 약 10MB입니다; 렌더링 중 디스크가 가득 차면
No space left on device오류가 발생합니다. 새 배치를 시작하기 전에df -h를 확인하고, 약 15GB 미만이면 먼저 정리할 수 있는 그룹(각 도구 캐시, conda clean 등)을 나열하여 사용자에게 선택권을 주고, 삭제는 사용자 동의를 받아야 합니다. - 장 제목 카드와 오프닝/엔딩 카드는 각 에피소드마다 약 10초가 추가되므로, TTS 실제 길이 + 10초로 완성본 길이를 추정합니다.
- 화면 agent가
src/covers/index.ts를 등록할 수 있습니다: 이는 커버 제작에 필요하므로 허용합니다. - 백그라운드에서 렌더링을 기다릴 때
pgrep -f render.sh를 사용하지 마십시오: 대기 명령 자체의 명령줄에도 이 단어가 포함되어 있어 pgrep이 항상 자신과 일치하여 몇 시간 동안 빈 상태로 대기합니다.out/epK.mp4(또는 로그의 오류)가 나타날 때만 기다리십시오.