Shorts Video Studio
30-60초 길이의 1080x1920 MP4 + SRT + 대본을 생성합니다. 모든 과정은 절차적(Python + OpenCV + PIL + ffmpeg)이며, 큐 기반 애니메이션 엔진으로 구동되어 시각 효과가 정확히 발화 단어에 맞춰집니다.
이 스킬의 파일
scripts/shorts_engine_template.py- 작동하는 참조 엔진 (9개 장면, 9개 배경, 8개 전환, 오디오, 음성 동기화). 복사해서 편집하세요. 처음부터 다시 작성하지 마세요.scripts/tts_elevenlabs.py- REST API를 통해 음성 해설 생성 (환경 변수ELEVENLABS_API_KEY필요). 먼저--check와--list-voices를 실행하세요.scripts/review_frames.py- 연속 스틸샷 + QA 증거: 길이, 코덱, 해상도, 통합 LUFS, 음량 범위, 실제 피크. 실패 시 0이 아닌 값으로 종료합니다.scripts/setup.sh-.venv가상 환경 생성, 의존성 설치, ffmpeg 및 폰트 확인. 이후source .venv/bin/activate를 실행하세요.assets/fonts/- 15개의 OFL-1.1 폰트 파일 / 12개 패밀리 + Noto Color Emoji (실제 아이콘). 라이선스 포함,assets/fonts/LICENSES.md에 인덱스 정리.references/design-bible.md- 팔레트, 폰트, 아이콘 어휘, 배경, 전환, 효과, 레이아웃 그리드. 장면 디자인 전에 반드시 읽으세요.references/script-and-voice.md- 대본 공식, Hinglish 규칙, 사실 확인 규칙, 음성 및 정렬 세부사항. 대본 작성 전에 반드시 읽으세요.
파이프라인 (순서대로 단계를 수행하세요)
- 조사 - 주제가 뉴스/트렌드인 경우, 웹 검색으로 3개 이상의 출처를 찾고 날짜와 숫자가 포함된 사실을 수집하세요 ("as of <날짜>"). 절대 숫자를 지어내지 마세요. 확인할 수 없는 주장은 표시하고 표현을 부드럽게 하세요 ("report ke mutabik").
- 대본 - 120-140 단어 (~45-50초 분량), 처음 2.5초 안에 훅, 7-9개의 짧은 비트, 마지막에 CTA. 자세한 내용은
script-and-voice.md를 참조하세요.script.txt로 저장하세요 (장면당 한 단락). - 장면 계획 - 단락당 한 장면. 각 장면에 대해 다음을 결정하세요: 배경 스타일, 팔레트, 2개 폰트, 아이콘 (이모지), 히어로 애니메이션, 큐 단어, 다음 장면으로의 전환. 아래 다양성 규칙을 적용하세요. 계획을
plan.md에 작성하세요. - 음성 - 전체 대본에 대해 단 하나의 음성 해설 테이크를 생성하세요 (
tts_elevenlabs.py또는 ElevenLabs MCP 사용).voice.mp3로 저장하세요. 오디오를 다운로드할 수 없는 경우 (샌드박스 환경), 사용자에게 파일 업로드를 요청하고, 그동안 예상 타이밍으로 빌드하세요. - 빌드 - 템플릿을
video.py로 복사하고, SCENES 텍스트를 교체하며,bgN/dN함수를 작성하고,HIT와TRANS를 설정하세요. 모든 애니메이션 시작에 큐 조회C(scene_idx, "spokenword", occurrence, default_seconds)를 사용하세요. - 테스트 렌더 -
TEST=1 python video.py는 PNG 파일을 생성합니다 (종료 상태, 중간 상태 및 전환당 한 프레임).review_frames.py를 실행하거나 직접 확인하세요. QA 게이트가 플래그하는 모든 것을 수정하세요. - 최종 렌더 -
VOICE=voice.mp3 python video.py를 실행하세요. 분리 모드로 실행하세요 (setsid nohup ... &). 로그를 폴링하고, 포그라운드 호출은 도구 타임아웃에 의해 종료될 수 있습니다. CPU 하나 기준 50초 영상에 약 1.5-3분 소요. 믹스는 자동으로LUFS(기본값 -16)로 음량 정규화됩니다. - QA 게이트 (아래 참조)를 최종 mp4에 대해 실행한 후,
video.mp4,captions.srt,script.txt,plan.md,qa_report.md를 전달하세요.
다양성 규칙 (이것이 AI 생성이 아닌 인간 제작처럼 보이게 만듭니다)
이 규칙 중 하나라도 위반하면 QA 게이트에서 FAIL 처리됩니다.
- 모든 장면은 고유한 배경 기법과 팔레트를 가져야 합니다 (광선, 신스웨이브 그리드, 하프톤 선버스트, 코드 레인, 그라데이션 + 블롭, 청사진 그린, 경고 줄무늬, 레이더 링, 컨페티 ...). 인접한 두 장면이 같아서는 안 됩니다. 전체 영상에 하나의 색상만 사용해서는 안 됩니다.
- 영상 전체에 걸쳐 >= 7개의 다른 폰트를 사용하여, 카테고리를 혼합해야 합니다: 좁은 임팩트, 덩치 큰 디스플레이, 넓은 디스플레이, 그로테스크, 세리프, 이탤릭 세리프, 모노스페이스, 픽셀, 손글씨. 한 장면 안에서는 최대 2-3개 폰트.
- >= 5개의 다른 텍스트 처리 방식: 그라데이션 채우기, 두꺼운 외곽선 + 하드 오프셋 그림자, 글로우, 글자별 바운스, 타자기, 스티커/알약 칩, 회전 도장, 손글씨 기울임.
- 실제 아이콘, 기하학적 도형이 아님: 아이콘으로 컬러 이모지(Noto Color Emoji)를 사용하고, 애니메이션 처리 (오버슈트와 함께 팝, 스핀인, 플로트, 오빗, 스윙). 텍스트만 있는 장면을 절대 제공하지 마세요. 브랜드 로고(Adobe, GitHub octocat 등)는 절대 사용하지 말고 일반 아이콘을 사용하세요.
- 장면 변경당 8개 이상의 다른 전환 효과: 글리치, 채찍 팬 블러, 줌 스루, 아이리스 + 링, 슬랫스 와이프, 플래시 + 쉐이크, 픽셀레이트, 푸시 업. 같은 전환을 두 번 사용하지 마세요.
- 임팩트 순간에는 결합 효과를 사용하세요: 스파크 버스트 + 쇼크웨이브 링 + 카메라 쉐이크 + RGB 스플릿 + 붐 SFX.
- 자막: 한 번에 2-3 단어, 크고 굵게 두꺼운 외곽선과 함께, 현재 단어는 장면의 색상으로 강조, 각 청크에 작은 팝 스케일.
- 모든 것이 움직여야 함: 아무것도 애니메이션 없이 나타나지 않으며, 아무것도 완전히 정지해 있지 않습니다 (유휴 시 흔들림 / 플로트 / 느린 줌 0 -> 3.5%).
레이아웃 및 안전 영역 (720x1280 작업 캔버스, 1080x1920으로 업스케일)
- 상단 0-130 px: 비워 둠 (플랫폼 UI). 태그 칩만 y~62 위치에 가능.
- 콘텐츠 영역 y 150-830. 자막 영역 중앙 y = 950 (H-330). 하단 250 px: 비워 둠 (플랫폼 UI).
- 너비 예산 640 px. 넘칠 수 있는 줄에는
TXF(text, size, font, maxw)를 사용하세요. 예상 너비 = 문자 수 x 0.55-0.75 x 크기 (넓은 디스플레이 폰트는 ~0.75). - 카운터: 고정 폰트 크기, 카운팅 중에 자동 축소하지 않음 (떨림 방지).
음성 및 동기화 (요약, 자세한 내용은 참조 문서)
- 하나의 테이크로 진행한 후 정렬:
apply_voice_peaks는 음절 에너지 피크를 감지하고 DP 매칭으로 대본의 음절과 연결합니다 (~0.2초 이내 안정).ALIGN=pauses는 명확한 일시 정지가 있는 느린 음성에 대한 대체 방식입니다. - 큐는 소문자, 구두점 제거된 텍스트가 토큰으로 시작하는 첫 번째 단어를 사용합니다 (숫자는 정확히 일치). 반복되는 단어에는
occurrence를 사용하세요. - 장면 시작 = 장면의 첫 번째 단어 - 0.45초. 총 길이는 음성 길이를 따릅니다 (+1.2초 테일).
- 음악은 합성(패드 + 킥 + 하이햇 + 베이스 + 아르페지오)되며 음성 아래에서 ~55% 음량이 자동 조절됩니다. 음성은 하이패스 + 컴프레션 + loudnorm (-15 LUFS) 처리가 적용됩니다. 모든 전환에 우쉬 사운드, 임팩트에 붐, 타이핑 틱, 카운터에 딩, CTA에 팝 사운드.
QA 게이트 (심사/QA 에이전트가 전달 전 반드시 모든 항목 통과해야 함)
python scripts/review_frames.py out/video.mp4 out/contact.png 12가 PASS를 출력해야 함 (그렇지 않으면 0이 아닌 값으로 종료). 음량 및 피크는 이 명령에서 가져오며,volumedetect에서 가져오지 않음.- 길이 30-60초, 1080x1920, h264+aac, 통합 음량 약 -18 ~ -13 LUFS, 실제 피크 < -1 dBTP (클리핑 없음).
- 9개 이상의 프레임 + 각 전환 프레임으로 구성된 연속 스틸샷 확인: 텍스트 잘림/오버플로우 없음, 요소 겹침 없음, 상단 130px 또는 하단 250px 내에는 태그/자막 외에 아무것도 없음, 모든 배경에서 자막을 읽을 수 있음.
- 다양성 규칙 충족 (
plan.md에 실제 사용된 폰트, 팔레트, 배경, 전환 목록 작성). - 사실: 대본의 모든 숫자/날짜/이름이
plan.md에 기록된 출처로 추적 가능해야 함. 검증되지 않은 주장은 표현을 부드럽게 할 것. 명시적으로 출처를 밝히지 않는 한 "copy"/"stole" 표현 사용 금지. 관련이 있을 때 알파/한계점 명시. - 동기화 샘플 점검: 5개의 큐(훅 단어, 숫자, 이름, 전환, CTA)를 선택하고 시각 효과가 발화 단어의 0.25초 이내에 시작하는지 확인 (SRT/
SW시간과 프레임 타임스탬프 비교). 검사 중 하나라도 실패하면: 수정, 재렌더링, 게이트 재실행. 남아있는 알려진 문제는 정직하게 보고할 것.
이미 겪었던 함정 (피하세요)
pip install을 시스템 Python에 실행하면 최신 Debian/Ubuntu에서 실패합니다 (externally-managed-environment, PEP 668).scripts/setup.sh(.venv생성)를 사용하고source .venv/bin/activate를 실행하세요.--break-system-packages를 사용하지 마세요.ffmpeg volumedetect의mean_volume(가중치 없는 dBFS)을 LUFS 목표와 비교하는 것은 의미가 없으며 이전 빌드에서 자체 게이트를 실패하게 만들었습니다. 항상ebur128로 측정하세요 (review_frames.py가 이미 수행).- PIL 이미지 또는 비연속적인 크롭에
Image.fromarray를 사용하면TypeError: expected string or buffer가 발생합니다. 스프라이트를 연속적인 numpy 배열로 유지하세요.rcard()는 PIL 이미지를 반환하며, 배열이 아닙니다. - 빈 배열 조각을
cv2.add에 전달하면 어설션 오류가 발생합니다. 밴드를 슬라이스하기 전에b > a를 보호하세요. setsid nohup없이 시작된 백그라운드 프로세스는 도구 호출이 반환될 때 종료됩니다.- 샌드박스 오디오 생성(MCP)은 샌드박스에서 다운로드할 수 없습니다. 사용자에게 mp3/wav 파일 업로드를 요청하세요.
- 일시 정지 기반 동기화는 빠른 AI 음성에서 실패합니다 (-35 dB에서 4개의 일시 정지만 발견). 피크 기반 정렬이 기본값입니다.
- 큐 윈도우 중복: 두 요소가 하나의 발화 단어를 공유하는 경우, 두 번째 요소를 0.2-0.4초 오프셋하세요.
- 변형 선택자가 있는 이모지 (예: 방패, 경고)는
embedded_color=True로 잘 렌더링됩니다. 크기 조정 시INTER_AREA축소 /INTER_CUBIC확대를 사용하세요. - 누락된 폰트는
[warn]라인과 함께 자동으로 DejaVu/Liberation으로 대체됩니다. 레이아웃을 탓하기 전에 렌더 로그에서[warn]을 확인하세요.