가사 비디오 표준 파이프라인
이미 검증된 고정 스타일입니다. 사용자는 오디오 파일과 가수 이름만 제공하면 되며, 나머지는 모두 이 표준에 따라 실행하고 시각적 요소를 재설계하지 마십시오. 공식 가사는 선택 사항입니다: 제공되면 3A 빠른 경로(텍스트 추측 없음)를, 제공되지 않으면 3B 재구성 경로를 따르며, 두 경로 모두 타임스탬프는 실측 기반이어야 합니다.
입력 / 산출물
| 입력 | 설명 |
|---|---|
| 오디오 | 필수. 모든 MP3/WAV/FLAC, 길이 제한 없음 |
| 가수 이름 | 필수. 인트로, 상시 모서리 표시, 아웃트로 서명에 사용 |
| 공식 가사 (선택 사항) | 사용자가 공식 가사를 가지고 있을 때 우선 사용: 텍스트 추측 없음, 타임스탬프는 모두 실측 재해석 기반(3A 참조). 제공되지 않으면 Whisper 재구성 사용(3B) |
| 곡 제목 (선택 사항) | 기본값은 파일 이름; Artist - Title.mp3 형식은 자동으로 가수 접두사 제거 |
| 테마 문구 (선택 사항) | 인트로 제목 아래 한 줄 중국어, 기본값은 표시 안 함 |
산출물: <project>/renders/video.mp4 + renders/contact-sheet.jpg + transcript.json + NOTES.md.
고정 사양 (임의 변경 불가)
- 세로형 1080 × 1920, 30 fps, 총 길이 오디오 실제 길이와 동일 (자르기, 늘리기, 변속 없음).
- 오디오는 원본 파일 사용, 렌더링 시 프레임워크가 통일 게인 조정(
data-volume="0.9"). - 배경: 순수 검정에서 극도로 어두운 청자색, 두 개의 오프셋 광점이 천천히 크로스 페이드 인; 전체 화면 CSS 필터 사용 금지 (분할 블록 이음새 발생).
- 주체: 하나만 있는 투명 유리체, 8가지 둥근 기하 윤곽(구/가로 타원/세로 타원/둥근 사각형/마름모/삼각형/오각형/육각형), 화면 가장자리에 충돌 시 법선 방향으로 11% 압축 → 0.94초 내에 다른 윤곽으로 변형 → 반동하며 계속 표류. 전체 곡 단일 타임라인, 가사 전환 시 재설정하지 않음.
- 하단: 작은 동물 밴드(고양이/곰/펭귄/여우) 4.5417초 무매끄러움 루프, 하단 고정 1080×526, 계층은 배경 광점 위, 유리체 아래,
mix-blend-mode: screen. - 자막: 전체 블록을 화면 수직 중심 y≈960을 광학 중심으로; 영어/원문 위쪽(Inter, 글꼴 크기는 행 너비에 따라 자동 조정), 중국어 아래쪽(SimSun, 따뜻한 갈색
#DDA97D), 같은 그룹 페이드 인/아웃. - 서명은 가수 이름으로 통일, 화면에 VERSE / CHORUS / BRIDGE 등의 구절 태그를 표시하지 않음.
세부 매개변수, 색상, 글꼴 크기, 주의사항은 references/style-spec.md 참조.
프로세스
HF = HyperFrames 설치 루트 디렉토리(기본 G:\hyperframes),
PY = faster-whisper가 포함된 Python(기본 C:\Users\Admin\.workbuddy-ai\binaries\python\envs\hf\Scripts\python.exe),
SK = 이 스킬 디렉토리.
1. 프로젝트 생성
"$PY" "$SK/scripts/new_project.py" "<오디오 경로>" "<가수 이름>" [--title "곡 제목"] [--tagline "한 줄 중국어"] [--root G:/hyperframes/videos]
출력은 프로젝트 절대 경로이며, 반드시 기록해야 합니다. 이 스크립트는: 고유 디렉토리 생성 → 오디오 복사 → 16kHz 모노 WAV로 변환 → 공식
analyze-beatgrid.py 실행하여 audiomap.json 생성 → 밴드 스프라이트 시트와 GSAP 복사 → project.json 작성.
기존 프로젝트 디렉토리를 절대 덮어쓰지 않음; 이미 전달된 작업을 수정하려면 새 프로젝트를 생성해야 합니다.
2. 전사
"$PY" "$SK/scripts/transcribe.py" "<project>" --model medium.en --lang en
CPU int8로 3-4분 노래 기준 약 3-6분 소요. 비영어 노래는 --lang을 해당 언어로 바꾸고 --model에서 .en 제거.
산출물: whisper_raw.json (구간 + 단어 수준 타임스탬프).
혼합 언어 노래(영어+일본어, 영어+한국어 등)에는 transcribe.py를 사용하지 마십시오: --lang이 하나의 언어로 고정되며,
다른 언어는 첫 번째 언어로 강제로 받아쓰기됩니다 — 결과는 읽기에는 매끄러워 보이지만 모두 틀리며, 해석 불가보다 더 위험합니다.
대신 창별 자동 언어 감지를 사용하십시오:
"$PY" "$SK/scripts/transcribe_mixed.py" "<project>" --model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo"
14초 창 / 10초 스텝으로 디코딩하여 각 창이 자체 언어를 판별하고, 창 핵심 단어만 유지(겹치는 영역은 폐기, 중복 없음),
언어 지도를 출력하고 whisper_mixed.json에 씁니다. 먼저 언어 지도를 확인하십시오: 언어 전환 위치는 일반적으로 구절 경계입니다.
.en 모델(medium.en / small.en)은 순수 영어 모델로, 물리적으로 일본어를 출력할 수 없습니다. 혼합 언어 노래는 반드시 다국어 모델을 사용해야 합니다.
3A(공식 가사 있음) 경로에서는 이 단계가 선택 사항입니다: 타임스탬프는 프롬프트 재해석을 기반으로 하며, 혼합 언어 노래는 여전히 먼저 transcribe_mixed.py를 실행하여
언어 지도를 확인하고 각 창에 --lang en 또는 --lang ja를 사용할지 결정하는 것이 좋습니다.
3. 가사 소스 파일 작성 (이 단계는 직접 수행해야 함)
먼저 경로를 판단한 다음 <project>/lyrics_source.json을 작성하십시오.
3A 사용자가 공식 가사를 제공한 경우 (선호 경로)
- 텍스트를 한 줄도 바꾸지 않고 공식 가사 사용:
en슬롯은 공식 원문(영문 문장은 영어로, 일어 문장은 일어로, 한자/가나는 그대로),zh는 문장별 번역. - 타임스탬프는 전체 곡 전사 없음: 공식 가사를
initial_prompt로 사용하여 구역별 재해석으로 단어 수준 타임스탬프 획득(방법은 3.5 참조), 각 행에 명시적start/end작성,align_lyrics.py가 수동 채널로 행별 고정. - 공식 가사와 재해석 결과가 일치하지 않으면 → 모두 공식 가사 채택, 차이점을 NOTES.md에 기록하여 사용자 확인 요청. 세 가지 일반 유형: 표준 단어 형태 vs 오타, 발음 유사 단어, 무성 자음 오인.
- 공식 가사에서 한 번에 불러진, 각 행이 1초 미만으로 나뉜 두 행 → 자막을 한 행으로 병합 표시(텍스트 변경 없음, 나란히만), 병합 대조표를 NOTES.md에 작성.
- 공식 가사에 없는 의성어/즉흥 구간("Yeah,", 흥얼거림, 휘파람) → 자막 없음, 직접 작성하지 않음.
- 구조는 다음과 같이 작성:
{
"audio": "Artist - Title.mp3",
"models": ["large-v3-turbo — prompted window re-scans, official lyrics as initial_prompt"],
"lines": [
{"en": "Oh my god, they're coming again", "zh": "오 맙소사, 그들이 또 오고 있어", "start": 6.36, "end": 9.10, "lang": "en", "conf": "high"}
]
}
3B 공식 가사 없음 (재구성 경로)
whisper_raw.json(또는 혼합 언어 노래의 경우 whisper_mixed.json)을 읽어 가사 소스 작성:
{
"audio": "Artist - Title.mp3",
"models": ["faster-whisper medium.en — full track, word timestamps"],
"lines": [
{"en": "Sometimes I lay under the moon", "zh": "때때로 나는 달빛 아래 누워"},
{"en": "And thank God I'm breathing", "zh": "내가 여전히 숨 쉬고 있음에 신께 감사드려"}
]
}
두 경로의 공통 요구사항:
- 행 = 실제 가창 한 문장, 공식 구분 기준으로; Whisper가 너무 긴 문장을 합친 경우 분할.
- 영어 철자는 공식 가사 기준으로 교정(
'Cause/I've등 아포스트로피 유지), Whisper의 오자를 그대로 사용하지 마십시오. - 중국어는 문장별 번역, 어조가 노래와 일치해야 하며, 문장 누락, 병합, 자리 표시자 텍스트 금지.
- 반복되는 후렴은 매번 작성(「위와 동일」 사용 금지).
- 어떤 문장의 보컬이 반주에 묻혀 자동 정렬이 명확히 어긋나면 명시적 시간 제공(오디오 듣고 채움):
{"en": "...", "zh": "...", "start": 13.22, "end": 16.80}. - 중국어 노래/순수 음악: 중국어 노래는
en에 원문 입력,zh는 빈 문자열로 두고, 화면에는 한 행만 표시; 순수 음악은 이 스킬 적용 불가. - 혼합 언어 노래:
en슬롯은 해당 문장의 실제 언어 원문(영문 문장은 영어, 일어 문장은 일어, 한자/가나는 그대로),zh는 중국어 번역. 화면 자체가 「원문 + 중국어」 두 행이므로 혼합 배치가 레이아웃을 망치지 않음; 템플릿의 영어 행에는 이미Yu Gothic UI / Yu Gothic / Meiryo가 fallback으로 포함되어 있어 가나와 한자가 정상 출력됨.
3.5 프롬프트 재해석: 타임스탬프 정밀도의 핵심 수단
전체 곡 전사는 빠른 노래, 혼창, 빠른 말하기 구절에서 일반적으로 부정확합니다. 알려진 가사를 initial_prompt로 사용한 구역별 재해석은 정밀도 상한이 가장 높은 수단입니다 —
프롬프트 품질이 재해석 정밀도를 직접 결정: 공식 가사 > 추측 가사 > 프롬프트 없음. rescan_all.sh에 작성하여 전체 곡을 일괄 실행할 수 있습니다:
"$PY" "$SK/scripts/rescan.py" "<project>" --from 6.0 --to 20.0 \
--model "C:/Users/Admin/.cache/whisper-manual/large-v3-turbo" \
--lang en --prompt "<해당 창의 공식 가사 원문>"
핵심 사항:
- 전체 곡을 20–26초 창으로 자르고, 창 간 겹침 약 0.5초, 창별로 재해석;
large-v3-turboCPU int8 단일 창 약 5–10초. - 혼합 언어 노래는 각 창에서 en/ja 양방향 각각 해석: 양방향이 일치하는 단어 수준 시간만 채택, 한 방향에서만 나타난 단어는 다른 방향으로 재확인.
- 앞당김/시작점 불명확한 문장은 2초 좁은 창으로 추가 잠금(
--from 37.2 --to 39.2는 한 문장의 시작점만 잠금); 구역 창 시작점은 이전 문장 끝음에 의해 편향되기 쉬움. - 환각 처리: 재해석 시 같은 전체 문장을 15+번 반복 출력하는 경우가 있음 → 해당 창 폐기, 다른 언어 채널로 전환하거나 창을 줄여 재해석, 깨끗한 단일 시간만 사용, 환각을 가사 소스에 포함하지 마십시오.
- 각 재해석 결과는
rescan_<from>-<to>.json으로 저장하고 창 내 각 단어의 시작과 끝을 출력합니다. 이는 2차 디코딩이지 추정이 아닙니다; 숫자를 직접lyrics_source.json의start/end에 작성. - 반주에 묻혀
ooh로 처리되거나, 큰 덩어리로 합쳐지거나, 반복 문장이 삼켜진 구절도 마찬가지로 이 수단을 먼저 사용한 다음 덮어쓰기 값 작성; 모델 변경(small.en/medium.en)도 효과적.
4. 정렬 + 생성
"$PY" "$SK/scripts/align_lyrics.py" "<project>"
"$PY" "$SK/scripts/motion.py" "<project>"
"$PY" "$SK/scripts/gen_storyboard.py" "<project>"
"$PY" "$SK/scripts/build_frame.py" "<project>"
"$PY" "$SK/scripts/make_index.py" "<project>"
align_lyrics.py는 행별 시간표를 출력하고 두 가지 엄격한 검사를 수행합니다:
- 시작/끝에 완전히 맞지 않는 문장이 있으면 → 직접 오류를 출력하고 종료, 해당 문장들을 나열(추측 시간으로 넘어가지 않음).
- 중간에 맞지 않는 문장, 두 문장의 시작점이 같거나, 어떤 문장이 0.5초 미만으로 압축된 경우 →
REVIEW출력 후 종료 코드 2 반환.
이 두 경우가 발생하면 3.5단계로 돌아가 덮어쓰기 값을 보충하고, OK: every line anchored to a real sung timestamp가 출력될 때까지 반복.
이 단계를 건너뛰고 렌더링하지 마십시오. 3A 경로의 행은 모두 명시적 start/end(수동 채널)를 가지며, 모두 고정되고 0 gap-filled여야 함;
3B 경로는 단어 매칭에 의존하며, 맞지 않는 행은 3.5에 따라 시간 보충.
motion.py의 랜덤 시드는 「가수 이름 + 곡 제목」으로 결정됨 — 같은 노래를 다시 실행하면 경로가 완전히 동일하고, 다른 노래는 다른 경로.
5. 검증
cd "<project>"
node "$HF/packages/cli/bin/hyperframes.mjs" check .
node "$HF/packages/cli/bin/hyperframes.mjs" snapshot . --at "3,20,60,120" --no-end -o build/shots
반드시 충족: lint / runtime / layout / motion 0 error, contrast 모두 WCAG AA 통과.
그런 다음 실제로 스크린샷 확인: 유리체가 완전한지, 가사가 중앙에 있는지, 밴드가 하단에 있는지, 불필요한 버블이나 구절 태그가 없는지.
composition_file_too_large는 단일 프레임 파일이 300행을 초과하는 스타일 힌트로, 허용 가능(단일 타임라인 설계의 필연적 결과).
6. 렌더링 + 검수
node "$HF/packages/cli/bin/hyperframes.mjs" render . --skill=music-to-video -q delivery -o renders/video.mp4 --fps 30
"$PY" "$SK/scripts/verify.py" "<project>"
verify.py는 해상도/프레임률/길이 편차(한 프레임 이상 차이면 오류)를 확인하고 연락처 시트를 생성합니다. 반드시 연락처 시트를 확인하여
시작, 벌스, 후렴, 반복 구간, 끝부분에 모두 화면이 있고, 자막에 빈 구간이나 오정렬이 없는지 확인.
마지막으로 NOTES.md(사양, 타임스탬프 출처, 재현 명령, 검증 기록)를 작성하고, 완성본과 연락처 시트를 사용자에게 전달.
엄격한 규율
- BPM/비트 그리드로 가사 시간을推算하지 마십시오; 타임스탬프는 Whisper 실측(프롬프트 재해석 포함) 또는 수동 청음 덮어쓰기에서만 비롯되어야 함.
- 사용자가 제공한 공식 가사는 모든 모델 재구성 결과보다 우선함; 충돌 시 공식 가사 채택, 차이점을 NOTES.md에 작성하여 사용자 확인 요청.
- 「더 좋아 보인다」는 이유로 해상도, 프레임률, 길이, 서명 또는 자막 위치를 변경하지 마십시오.
- 검증 없이 오디오-비디오 동기화를 주장하지 마십시오; 모든 노래에서 프레임을 추출하여 확인.
- 자료 누락, 도구 사용 불가, 사양 충돌 → 명확히 보고, 추정 데이터로 결과를 위장하지 마십시오.
- 이미 전달된 프로젝트와 그 소스 파일은 읽기 전용으로 간주; 개정은 새 디렉토리를 생성해야 함.
환경 종속성
- HyperFrames:
node <HF>/packages/cli/bin/hyperframes.mjs(skills/music-to-video/scripts/analyze-beatgrid.py포함). - Python:
faster-whisper,librosa,soundfile,numpy,scipy,pillow. 누락 시python -m venv <env> && <env>/Scripts/pip install faster-whisper librosa soundfile numpy scipy pillow. - Whisper 모델: 모델 이름을 직접 전달하면 자동 다운로드; 로컬 디렉토리로 지정 가능(본 기기에서 자주 사용하는
C:\Users\Admin\.cache\whisper-manual\medium.en; 프롬프트 재해석 선호C:\Users\Admin\.cache\whisper-manual\large-v3-turbo, CPU int8 전체 곡 약 48초, 단일 창 5–10초). - ffmpeg / ffprobe는 PATH에 있어야 함.
알려진 함정
- 밴드 레이어에
<video>사용 금지: 본 기기의hyperframes render는 Windows에서 추출 프레임 디렉토리를 컴파일 디렉토리에 링크한 후 읽기 실패(ENOENT ... __hyperframes_video_frames/*/frame_00001.jpg). 스프라이트 시트 사용. - 전체 화면 CSS
filter: hue-rotate()는 렌더링에서 세로 방향 이음새를 남깁니다. 대신 두 레이어 광점 크로스 페이드 인 사용. data-composition-id가 있는 템플릿 HTML은 프로젝트 루트 디렉토리에 두지 마십시오(multiple_root_compositions트리거).build/에 배치.- 중문 글꼴은 명시적으로
@font-face선언으로local("SimSun")을 지정해야 합니다. 그렇지 않으면 lint가font_family_without_font_face오류를 보고. - 재해석 환각: 특정 창에서 같은 전체 문장을 15+번 반복 출력(예: 「永遠の行方はどこにある?」×15) → 해당 창 폐기, 교차 en 채널로 전환하거나 창을 줄여 재해석, 환각 타임스탬프를 가사 소스에 포함하지 마십시오.
- 공식 가사 vs 재해석 불일치: 공식 가사 채택하고 NOTES.md에 대조표를 작성하여 사용자 확인 요청, 공식 텍스트를 임의로 수정하지 마십시오.
- 빠른 말하기 병합 행: 공식 가사에서 한 번에 불러진, 나뉜 각 행이 1초 미만인 두 행, 자막을 한 행으로 병합 표시(텍스트 변경 없음, 나란히만), 병합 대조표를 NOTES.md에 작성.
- headless 글꼴 로딩 실패(프레임 추출 시 Yu Gothic UI가 FAILED 보고)는 당황하지 마십시오:
src: local()의 글꼴은 시스템에 설치되어 있으면 브라우저가 일반적으로 찾으며, 다음 순위 글꼴도 fallback을 제공하므로, 먼저 스크린샷을 확인한 후 처리 여부 결정.
관련 링크
참고: style-spec.md