Communitygithub.com

Orinkle/ideaform

구성주의 해설 영상을 제작하는 4단계 파이프라인: 원고 → TTS 해설 음성(시간축) → LMMS BGM(변주로 논의 계층 표시) → Remotion 렌더링 및 썸네일. 사용자가 해설/지식/구술 영상을 만들거나 '해설 음성을 시간축으로 삼고 BGM이 논의 계층에 따라 변주되는' 최종 영상을 제작할 때 사용합니다. 전제: ideaform-setup으로 환경을 설정하고 toolchain.json 경로 계약을 작성한 상태여야 합니다.

ideaform란 무엇인가요?

이 기술(스킬)은 '구성주의 해설 영상' 제작을 위한 완전한 4단계 파이프라인으로, 원고 작성, TTS(텍스트 음성 변환)를 통한 시간축 설정, LMMS(리눅스 멀트미디어 스튜디오)를 이용한 배경 음악(BGM) 변주, 그리고 Remotion을 통한 최종 렌더링 및 썸네일 생성을 포함합니다. 핵심 철학은 해설 음성을 절대적인 시간축으로 삼고, 화면과 BGM이 이 축에 종속되도록 설계한다는 점입니다. 특히 BGM의 변주점은 원고의 논리적 계층 전환 지점에 정확히 맞춰져 시청각적 일관성을 높입니다. 코드, 명령어, 파일 경로 등 기술적 요소는 원본을 유지하며, 사용자는 설정 스크립트(ideaform-setup)를 통해 환경을 사전에 구축해야 합니다. 이 기술은 Claude Code, Cursor, Codex 등 다양한 AI 에이전트 플랫폼에서 활용할 수 있으며, 각 단계별로 자세한 참조 문서를 제공하여 실수를 방지하고 품질을 보장합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Orinkle/ideaform/tree/HEAD/skills/ideaform

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

구성주의 해설 영상 · 워크플로우

하나의 시간축, 세 개의 하위 단계가 모두 여기서 파생됩니다.

① 원고            ② TTS 축 설정                ③ BGM 변주            ④ 최종 영상
   텍스트    ──→   해설 음성(시간축)        ──→   LMMS 음악(계층)     ──→   Remotion 화면 + 음성 트랙 통합 + 썸네일
                          │                        ▲
                          └──── 계층 경계 시간 지점 ────┘
  • 화면 프레임 수는 TTS의 자연스러운 속도에 따라 결정됩니다 (반대로 속도를 압축하지 않음).
  • BGM의 변주점은 해설의 계층 전환 지점에 맞춥니다.
  • 최종 영상은 해설 음성을 기준으로 정렬되며, BGM은 배경으로만 사용됩니다.

0. 시작하기: 먼저 경로 계약을 읽으세요 (이 단계는 생략할 수 없습니다)

이 스킬은 자체적으로 도구를 찾지 않으며, 모든 경로는 환경 설정 스킬이 작성한 계약에서 가져옵니다:

$VW_CONTRACT  (기본값 ~/.config/ideaform/toolchain.json)
CONTRACT="${VW_CONTRACT:-$HOME/.config/ideaform/toolchain.json}"
source "$(dirname "$CONTRACT")/env.sh"     # VW_NODE / VW_VENV / VW_FFMPEG / … 내보내기

작업 시작 전에 반드시 확인해야 할 세 가지:

  1. 계약 파일이 존재합니까? 없으면 → 사용자에게 먼저 ideaform-setup 스킬을 실행하도록 안내합니다.
  2. schema_version이 이 스킬이 인식하는 버전입니까? 일치하지 않으면 → 환경 설정 스킬을 다시 실행하도록 요청합니다.
  3. verified_at이 null입니까? 그렇다면 → "환경이 초기 검증을 통과하지 못했습니다" 사용자에게 경고하고, 먼저 수정한 후 작업을 진행합니다. 또한 tools.lmms.stkdir_ok는 반드시 true여야 합니다. 그렇지 않으면 BGM이 전체적으로 무음이 되며 오류도 발생하지 않습니다.

주요 필드 빠른 참조:

용도계약 필드
TTS 스크립트 실행 (venv 내 edge-tts)tools.venv.python
오디오/비디오 합성tools.ffmpeg.path / tools.ffprobe.path
화면 렌더링tools.remotion.project / tools.remotion.browser.resolved
BGM 렌더링tools.lmms.apprun
임시 파일 저장 (대용량 디스크 필수)tmpdir

⚠️ 계약의 tmpdir은 선택 사항이 아닙니다. 로컬 /tmp는 10MB에 불과하며, Remotion 패키징 / pip 패키지 설치 시 이를 사용하므로 ENOSPC 오류가 발생합니다. 모든 Remotion 명령에는 TMPDIR을 포함시켜야 합니다.

⚠️ 경로는 절대 resolve(심볼릭 링크 해석)하지 마세요. 관리형 툴체인 경로에는 심볼릭 링크가 포함되어 있으며, venv 인터프리터를 해석하면 venv 컨텍스트가 손실되어 모든 패키지를 가져올 수 없습니다. 자세한 내용은 저장소 루트의 docs/03-경로-계약.md를 참조하세요.


1. 4단계 개요

단계수행 작업입력출력 (작업 공간에 저장)참조
① 원고사용자 입력을 계층화된 해설 원고로 변환사용자 입력script.md + 대사.txt (계층 표시 완료)references/stage1-script.md
② TTS 축 설정자연스러운 속도 측정 → 시간축 생성 → 음성 트랙 출력대사.txtplan.json / timeline.ts / voice.wavreferences/stage2-tts.md
③ BGM 변주계층 경계 → 변주 계획 → LMMS 음악 트랙 출력plan.json + 계층 표시bgm-plan.json / bgm.wavreferences/stage3-bgm.md
④ 최종 영상Remotion으로 화면 배치 + 트랙 통합 + 렌더링 + 썸네일timeline.ts + 오디오 트랙 + bgm-plan.jsonfinal.mp4 + cover.pngreferences/stage4-render.md · references/cover.md

스타일 통일은 references/constructivist-style.md가 관리합니다. 화면과 썸네일이 동일한 색상 팔레트 / 폰트 / 그리드를 사용하므로 자연스럽게 일관성을 유지합니다.


2. 1단계 · 원고 (계층화는 필수)

사용자가 제공하는 것은 입력(주제 / 자료 / 구상)입니다. 결과물은:

  • script.md —— 전체 원고, 논의 계층을 명시적으로 표시
  • 대사.txt —— 한 줄에 한 문장의 구술 대사, TTS에서 사용

계층화는 보기 좋으라고 하는 것이 아니라, 3단계의 입력입니다. 계층 표시가 없으면 BGM 변주는 기준점을 잡을 수 없습니다.

## 계층 1 · 도입
이것은 《원고가 시간축이다》의 첫 번째 계층입니다.
해설 음성이야말로 전체 파이프라인의 시간축입니다.
## 계층 2 · 전개
화면 프레임 수는 이것에 의해 결정되며, 그 반대가 아닙니다.
...
  • 한 문장 = 하나의 의미 단위, 두 가지 내용을 한 문장에 넣지 마세요 (TTS는 문장 단위로 축을 정하므로, 두 내용을 넣으면 슬롯이 길어집니다).
  • 한 문장은 8–30자를 권장합니다. 너무 길면 문장을 나누고, 너무 짧으면 합칩니다.
  • 문장 부호는 마침표/물음표로 끝내 TTS의 문장 구분을 돕습니다.

자세한 내용은 references/stage1-script.md를 참조하세요.


3. 2단계 · TTS 축 설정 (순서는 철칙)

"$VW_VENV/bin/python" skills/ideaform/scripts/make-tts-track.py \
    --lines 대사.txt --fps 30 --audio \
    --plan-out out/plan.json --ts-out out/timeline.ts

먼저 음성을 녹음하고, 그 다음 축을 설정합니다. 시간축은 TTS의 실제 속도에서 생성됩니다:

① 대사 작성
② make-tts-track.py --lines 대사.txt --fps 30 --audio   ← 자연스러운 속도 측정, 시간축 생성
③ 출력된 TOTAL_FRAMES를 사용하여 Remotion composition 작성       ← 프레임 수가 이에 따라 결정됨
④ 그런 다음 렌더링

반례의 대가 (실제 사례): 먼저 스토리보드에 따라 43개의 타임코드를 고정하고, TTS 자연 속도가 총 212.90초인데 비디오는 174.80초에 불과하여 → 1.218배 강제 압축을 해야 했습니다. 이 타협은 충분히 피할 수 있었습니다.

같은 스크립트로 반대 작업도 가능합니다 (이미 SRT가 있고 타임코드가 고정된 경우 두 단계 속도 조정으로 적응), 하지만 그것은 보완일 뿐 최선의 방법은 아닙니다. 자세한 내용은 references/stage2-tts.md를 참조하세요.

⚠️ 사용자에게 "최종 영상이 몇 분인지" 묻는 것을 금지합니다. 길이 = 속도 × 대사량, 즉 출력이지 입력이 아닙니다. 작업 시작 시 묻거나 "표준판 X분"과 같은 옵션을 제공해서는 안 됩니다. 「이 원고 기준으로 실제 측정 결과 X분 Y초입니다」라고만 보고합니다. 사용자가 더 길거나/짧게 원하면 → 변경해야 할 것은 원고이지, 시간이 아닙니다. (2026-10-15 계화편에서 겪음, E16 참고)

출력: plan.json의 각 cue에는 start/end/dur/frameStart/frameEnd가 포함됩니다. timeline.ts는 바로 cp하여 Remotion 프로젝트의 src/timeline.ts로 사용할 수 있습니다.


4. 3단계 · BGM 변주 (이 워크플로우의 핵심)

요점: 논의가 새로운 계층에 진입할 때마다 음악의 형태가 바뀝니다. 단, 곡 자체는 바뀌지 않습니다.

# ① 원고의 계층을 cue 번호에 매핑하고, 각 계층의 서사 기능을 표시합니다
"$VW_VENV/bin/python" skills/ideaform/scripts/bgm-plan.py \
    --plan out/plan.json \
    --layers "1:present,4:develop,6:resolve" \
    --key "A minor" --out out/bgm-plan.json

# ② bgm-plan.json에 따라 LMMS 프로젝트를 생성하고 렌더링합니다 (electronic-music-production의 composer.py 사용)
#    계약의 tools.lmms.apprun으로 렌더링합니다. bpm 및 timeline lp1pos는 mmp_hints에 따라 작성해야 합니다.

여섯 가지 서사 기능 (각 계층에서 하나를 선택):

기능의도변경 사항
present제시·도입동기만 노출, 단성부, 여백
develop전개·심화+베이스 +리듬, 동기 시퀀싱
intensify강조·충돌전성부, 옥타브 상승, 차용 화음, 강도 증가
contrast대조·전환볼륨 증가 없이 질감 변경: 레이어 제거, 음색 변경, 조성 전환
resolve수렴·회귀간소화, 본조 회귀, 동기 증대
sustain지속·전환변경 없음 (계층이 변경되지 않았는데 변주하면 대비가 희석됨)

철칙:

  • 정체성 요소는 변경 불가 —— 동기 세포, 조성 중심, 기본 속도. 변경되면 변주가 아니라 곡이 바뀌는 것입니다.
  • 각 구간은 최소 1개의 형태 요소를 변경해야 합니다. bgm-plan.md에는 각 구간의 「변주 증거」가 나열됩니다. 인접한 두 구간의 증거가 비어 있으면 계층 표시가 누락된 것입니다.
  • 변주 지점은 해설의 계층 경계에 정확히 맞춰야 합니다 (--lead-in을 사용하여 음악이 약간 앞서 시작하도록 할 수 있음).

전체 방법 및 LMMS 측 구현은 references/stage3-bgm.md를 참조하세요.


5. 4단계 · 최종 영상

5.1 화면: 해설 음성을 시간축으로

cp out/timeline.ts <remotion-프로젝트>/src/timeline.ts     # 프레임 수/씬 경계를 모두 CUES에서 도출
cd <remotion-프로젝트>
export TMPDIR="$VW_TMPDIR"                             # ★ 필수
npx remotion studio                                    # 먼저 사용자에게 미리보기 제공

화면 씬의 경계는 프레임 번호를 직접 입력하지 말고, CUES에서 도출하세요:

export const SCENES = {
  s1: { from: 0,            dur: CUES[2].start },
  s2: { from: CUES[2].start, dur: CUES[4].start - CUES[2].start },
} as const;

구조식 / 신호 경로 / 메커니즘 다이어그램 → 모두 결정론적으로 생성하며, 절대 AI 이미지 생성을 사용하지 마세요. AI가 화학 구조를 그리면 반드시 환각 결합을 만들어 내며, 오류를 발견할 수 없습니다——이러한 자료는 재현 가능하고 검증 가능해야 합니다. scripts/gen-structures.py 사용: SMILES → RDKit 결정론적 묘사 → 프레임 기반 Remotion 컴포넌트

python3 scripts/gen-structures.py --tsv structures.tsv --out structures
#   → svg/*.svg  +  components/*.tsx (자체 애니메이션 포함)  +  manifest.json
#   → 분자식 오프라인 검증 (RDKit CalcMolFormula), 불일치 시 0이 아닌 종료 코드 반환, `&&`로 직접 연결 가능
  • 색상은 RDKit 공식 옵션(useBWAtomPalette / singleColourBonds / setSymbolColour)을 사용하고, 정규식으로 SVG의 색상을 후처리하지 마세요——이는 반복 작업이며 RDKit 버전 업데이트 시 깨집니다 (오답노트 E20 참고).
  • 생성된 컴포넌트는 CSS 변수 --mol-dash / --mol-text를 사용하여 선 애니메이션을 구동하므로, 외부에서 반드시 color를 제공해야 합니다.
  • 그리드 다이어그램 / 골격 강조 / 3D 형태 / 단백질-리간드 상호작용 다이어그램 등 더 광범위한 분자 시각화가 필요하면, 먼저 기존 스킬을 찾아보세요 (§7 참조), 비디오 파이프라인에 억지로 포함하지 마세요.

5.2 오디오 트랙 통합 (두 가지 방법, 기본 A)

A. Remotion 통합 (권장) —— composition에서 <Audio>를 사용하면 렌더링된 mp4에 자동으로 오디오 트랙이 포함됩니다:

<Audio src={staticFile("voice.wav")} />
<Audio src={staticFile("bgm.wav")} volume={0.1694} />

volume 값은 임의로 정하지 말고, 실제 RMS를 측정하여 역산합니다:

bash scripts/mix-av.sh --plan-only --voice voice.wav --bgm bgm.wav --drop 9
# 해설 RMS = -23.46 dBFS   BGM RMS = -17.04 dBFS
# → BGM에 -15.42 dB 적용 →  volume = 0.1694

B. 후반 합성 (비디오가 이미 렌더링되었거나 / 음성을 다시 녹음해야 하는 경우):

bash scripts/mix-av.sh --video silent.mp4 --voice voice.wav --bgm bgm.wav --out final.mp4

⚠️ 방법 B는 반드시 명시적으로 -map 0:v:0 -map 1:a:0을 사용해야 합니다. Remotion이 출력하는 mp4에는 무음 AAC 트랙이 포함되어 있습니다. -map을 추가하지 않으면 ffmpeg가 자동으로 이 트랙을 선택하여 → 최종 파일의 종료 코드는 0, 길이는 정확, 재생은 가능하지만 소리가 없습니다. mix-av.sh에는 이 -map이 이미 내장되어 있습니다.

5.3 렌더링 및 썸네일

export TMPDIR="$VW_TMPDIR"
npx remotion render <CompositionId> out/video.mp4 --concurrency=3
npx remotion still Cover out/cover.png --props='{...}'    # 썸네일: 정적 composition, 애니메이션 사용 금지
  • 긴 영상 분할 렌더링: 7분 영상을 한 번에 렌더링하면 메모리 부족으로 시간 초과가 발생할 수 있습니다. --frames=A-B로 분할 → concat -c copy 무손실 병합.
  • 썸네일은 durationInFrames={1}인 정적 composition을 사용하고, 컴포넌트 내에서 useCurrentFrame을 사용하지 마세요 (still 시 항상 0이므로 애니메이션 초기값으로 인해 요소가 보이지 않을 수 있습니다).
  • 썸네일 레이아웃은 references/cover.md를, 스타일 규칙은 references/constructivist-style.md를 참조하세요.

6. 눈 없는 검증: 각 단계마다 검증기를 통과해야 합니다

모델은 이미지를 볼 수 없고, 소리를 들을 수 없습니다. 따라서 "렌더링 성공" ≠ "화면 맞음, 소리 맞음"입니다. 각 단계는 수치로 실제 측정하며, 기준을 통과하지 못하면 전달을 거부합니다:

# 오디오 자체 점검 (TTS 트랙, BGM): 피크/RMS/클리핑/길이 편차
# 화면 자체 점검: 픽셀 색상 / 여백 순도 / 텍스트 픽셀 개수
#   --layout은 반드시 올바르게 선택: cover=썸네일 레이아웃; scene=비디오 씬 (기본값).
#   샘플링 스트립은 레이아웃에 따라 결정되며, 잘못 사용하면 올바른 썸네일도 실패 판정을 받을 수 있습니다 (05-문제 해결 D2 참고).
python3 scripts/verify-video.py cover out/cover.png --layout cover

# 최종 영상 자체 점검: 프레임 수 / 길이 / 오디오 트랙 비트레이트 (무음 트랙 방지)
# ffprobe 위치 순서: VW_FFPROBE → 경로 계약 toolchain.json → 시스템
VW_FFPROBE="$VW_FFPROBE" python3 scripts/verify-video.py video out/final.mp4 --frames 732 --fps 30

스크립트는 0이 아닌 종료 코드로 실패를 나타내며, && 파이프라인에 직접 연결할 수 있습니다.

자주 사용되는 판정 기준 빠른 참조:

대상판정 기준임계값
오디오무음 아님피크 > 1000 및 RMS > 100
오디오클리핑 없음전체 스케일 샘플 < 0.01%
오디오길이 정렬계획과의 편차 < 50 ms
썸네일크기1920×1080
썸네일텍스트 렌더링텍스트 영역 잉크 픽셀 > 300
썸네일축선 텍스트 미침제목 영역 내 빨간색 픽셀 < 60
최종 영상프레임 수계획 값과 정확히 일치
최종 영상오디오 트랙 무음 아님비트레이트 > 64000 bps
BGM배경 레벨나레이션보다 8–12 dB 낮음

7. 이 스킬과 함께 사용할 수 있는 다른 기능

필요한 것사용할 것
환경 탐지 / 보완 설치 / 계약ideaform-setup (일회성)
새로운 오픈 소스 도구의 기존 스킬 (가져오기: GitHub 수집 → 보안 검사 → 저장)ideaform-setup의 scripts/harvest-skills.py <도구명>
화학 구조식 / 경로 다이어그램의 결정론적 그래픽이 스킬의 scripts/gen-structures.py (RDKit → SVG → Remotion 컴포넌트)
더 광범위한 분자 시각화 (그리드 다이어그램 / 골격 강조 / 3D 형태 / 단백질-리간드)외부 기존 스킬: synthetic-sciences/openscience의 molecule-visualization (Apache-2.0), ghutchis/chem-skill (MIT)
LMMS 프로젝트 형식, 플러그인 매개변수, eldata 엔벨로프electronic-music-production + 그 references/05
작곡법 (화성, 동기, 무청각 작곡, 창발)electronic-music-production의 references/06–10
Remotion 문법 및 렌더링 세부 사항remotion-best-practices
픽셀 수준 눈 없는 검증의 전체 방법headless-visual-verify
WSL 환경 함정 (/mnt, gh 가져오기, 오디오 경로)wsl-pitfalls

8. 전달 목록

한 편의 비디오가 완성되면 작업 공간에는 다음이 있어야 합니다:

<작업 공간>/
├── script.md            계층화 원고
├── 대사.txt              구술 대사
├── out/
│   ├── plan.json        시간축 (각 cue의 초/프레임)
│   ├── timeline.ts      Remotion에 바로 사용 가능한 시간축
│   ├── voice.wav        해설 음성 마스터
│   ├── bgm-plan.json    변주 계획 + bgm-plan.md (변주 증거)
│   ├── bgm.wav          BGM 트랙
│   ├── video.mp4        무음 화면 (또는 오디오가 통합된 최종 영상)
│   ├── final.mp4        ★ 최종 영상
│   └── cover.png        ★ 썸네일
└── .tts/                TTS 캐시 (유지, 재실행 시 몇 초만 소요)

전달 전에 반드시 섹션 6의 모든 검증을 실행하고, 어떤 항목이 통과했고 어떤 항목이 테스트되지 않았는지 정확히 보고해야 합니다.


9. 자체 진화: 문제가 발생하면 기록하세요

이 워크플로우는 변경 가능한 복합 스킬입니다——사용하면서 생산 리듬에 더 잘 맞도록 발전해야 합니다.

  • 문제가 발생하여 수정한 직후 → 저장소 루트의 docs/06-오답노트.md에 기록합니다 (6열 형식, 번호 순차적으로 증가). ⚠️ skills/ideaform/ 아래에 별도의 docs/를 만들지 마세요——중복 장부가 되며 원본과 번호가 충돌합니다 (2026-10-15에 겪음, E19 참고).
  • 특정 문제가 스크립트/문서로 영구적으로 수정된 경우 (우회가 아님) → 해당 항목의 상태를 완치로 변경하고 수정 방법을 명시합니다.
  • 동일한 유형의 문제가 두 번째로 발생하면 → 세 번째 항목을 기록하지 말고, 방어선을 스크립트에 직접 작성합니다 (검증기 / 기본값 / 계약).
  • 새로운 오픈 소스 도구 도입 → 먼저 수집한 후 작업 시작: harvest-skills.py <도구명>으로 커뮤니티의 성숙한 스킬을 찾습니다 (분기 보호가 있어 로컬에서 수정한 내용을 덮어쓰지 않습니다); 적합한 것을 찾지 못한 경우에만 직접 작성합니다. 수집한 스킬에서 문제가 발생해도 동일하게 기록합니다.
  • 세션 종료 전에 확인: "수정했지만 기록하지 않은 것"이 있는지 확인합니다.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬