OpenCaptions 확장
CWI(Caption With Intent) 자막을 Content Engine 포스트 프로덕션 파이프라인에 연결합니다. 평평하고 정적인 자막 대신, CWI는 음성의 느껴지는 경험을 인코딩합니다. 음높이는 폰트 두께, 음량은 폰트 크기, 강조는 글로우 애니메이션, 화자 식별자는 WCAG AA 색상을 구동합니다. 결과는 무엇이 말해졌는지뿐 아니라 어떻게 말해졌는지를 전달하는 자막입니다.
CWI는 FCB Chicago와 Chicago Hearing Society가 제정한 2025년 오스카 수상 자막 표준입니다. OpenCaptions는 이를 위한 최초의 오픈소스 프로그래매틱 툴체인입니다.
파이프라인 연결 지점
단계: 포스트 프로덕션(Stage 3) 위치: Upscale 및 Color Grade 후, 최종 Export 전.
포스트 프로덕션 체인:
1. Upscale (Real-ESRGAN / Topaz) --> 더 높은 해상도
2. Color Grade (Brand LUT / ffmpeg) --> 브랜드 색상
3. OpenCaptions (CWI) --> 의도 기반 자막
4. Final Export (ffmpeg) --> 프로덕션 준비 파일
확장은 그레이딩된 비디오 파일을 입력받아 다음을 생성합니다:
- 단어 수준 의도 주석이 포함된 CWI 문서 (
.cwi.json) - 표준 자막이 필요한 플랫폼을 위한 WebVTT 폴백 (
.vtt) - 기둥 점수가 포함된 검증 보고서 (JSON)
- Remotion 또는 ffmpeg burn-in으로 렌더링된 자막 비디오 (
.mp4)
작동 방식
그레이딩된 비디오 + 장면 브리프
|
├── [1] 전사 (faster-whisper) --> 단어 수준 타임스탬프
├── [2] 화자 분리 (pyannote-audio) --> 화자 속성
├── [3] 의도 추출 --> 발화별 음높이, 음량, 감정, 강조
| V1: parselmouth + FER (오디오+비전)
| V2: V-JEPA2 월드 모델
| V3: TRIBE v2 신경망 예측
├── [4] 의도 --> CWI 매핑 --> 단어별 두께, 크기, 강조, 애니메이션
| V1: RulesMapper (음높이-->두께, 음량-->크기)
| V2: LearnedMapper (수정 데이터로 학습)
| V3: NeuralMapper (뇌 영역 활성화가 스타일링을 구동)
├── [5] 검증 (12개 규칙) --> 속성 + 동기화 + 억양 점수
└── [6] 렌더링 --> Remotion 오버레이 또는 ffmpeg burn-in
단계 1-2: 전사 + 화자 분리
파이프라인은 OpenCaptions CLI 또는 MCP 서버를 호출하며, 이는 faster-whisper로 단어 수준 타임스탬프를, pyannote-audio로 화자 감지를 실행합니다. 이 단계는 각 단어가 화자에 태그된 DiarizedTranscript를 생성합니다.
단계 3: 의도 추출
의도 추출기는 오디오와 비디오를 분석하여 각 발화의 느껴지는 레지스터를 결정합니다:
- 음성 신호: 음높이(Hz), 음량(dB), 발화 속도(WPM), 일시 정지 타이밍
- 감정 신호: 원자가(-1 ~ 1), 각성(0 ~ 1), 지배적 감정
- 의미 신호: 비꼼 확률, 강조 단어, 수사적 장치
이러한 신호는 각 발화에 대한 IntentFrame을 형성합니다. 발화 기준선에서 벗어나는 개별 단어는 WordIntent 재정의를 받습니다.
단계 4: 의도 매핑
매퍼는 의도 신호를 CWI 시각 매개변수로 변환합니다:
| 의도 신호 | CWI 속성 | 매핑 (V1 RulesMapper) |
|---|---|---|
| 음높이 (정규화 0-1) | weight (100-900) | 선형 보간: 100 + pitch_norm * 800 |
| 음량 (정규화 0-1) | size (0.7-1.5) | 선형 보간: 0.8 + volume_norm * 0.55 |
| 의미적 강조 + 높은 음량 | emphasis (boolean) | 단어가 emphasis_words에 있거나 음량 > p90 |
| 화자 식별자 | 화자 color | 12색 WCAG AA 팔레트에서 할당 |
| 속삭임 (낮은 음량) | weight < 300 | 재정의: 두께 100-250으로 고정 |
| 외침 (높은 음량) | size > 1.3 + emphasis | 재정의: 크기 1.35-1.5, emphasis true |
단계 5: 검증
@opencaptions/spec 검증기는 세 가지 기둥에 걸쳐 12개 규칙에 대해 CWI 문서를 확인합니다:
속성 (3 규칙):
- ATT_001: 모든 자막에 출연진의 화자가 있습니다.
- ATT_002: 화자는 고유한 색상을 가집니다.
- ATT_003: 색상이 WCAG AA 대비를 충족합니다 (4.5:1 대비 #1a1a1a 기준).
동기화 (5 규칙):
- SYN_001: 모든 단어에 타임스탬프가 있습니다.
- SYN_002: 타임스탬프가 단조 증가합니다.
- SYN_003: 자막 이벤트가 겹치지 않습니다.
- SYN_004: 애니메이션 지속 시간이 사양에 따라 600ms입니다.
- FCC_001: 음성 중 3초 이상 간격이 없습니다.
- FCC_002: 줄당 최대 42자(FCC 준수).
억양 (3 규칙):
- INT_001: 두께가 유효 범위 내에 있습니다 (100-900).
- INT_002: 크기가 유효 범위 내에 있습니다 (0.7-1.5).
- INT_003: 20% 이상의 단어가 기본값이 아닌 두께를 가집니다 (자막이 실제로 다양함).
각 기둥은 0-100점을 얻습니다. 세 기둥 모두 점수가 80점 이상이면 CWI 문서가 통과됩니다.
단계 6: 렌더링
두 가지 렌더링 경로:
Remotion 경로 (Content Engine에 권장): CWI 단어는 <CaptionOverlay> 구성에서 React 구성 요소가 됩니다. 각 단어는 타임스탬프에 spring() 진입 애니메이션, 화자 색상, 가변 폰트 두께, 강조 글로우와 함께 나타납니다. 전체 매핑은 references/cwi-remotion-bridge.md를 참조하십시오.
ffmpeg burn-in (폴백): CWI 문서에서 ASS 자막 파일을 생성하고 ffmpeg -vf ass=captions.ass를 통해 비디오에 굽습니다. 단어별 애니메이션은 손실되지만 화자 색상과 폰트 두께 변형은 유지됩니다.
CLI 사용법
# 비디오에서 CWI 자막 생성
npx opencaptions generate video.mp4 --output captions.cwi.json
# TRIBE v2 신경망 백엔드로 생성
npx opencaptions generate video.mp4 --backend tribe --output captions.cwi.json
# CWI 문서 검증
npx opencaptions validate captions.cwi.json
# 터미널에서 자막 미리보기 (ANSI 색상)
npx opencaptions preview captions.cwi.json
# WebVTT로 내보내기
npx opencaptions export captions.cwi.json --format webvtt
# After Effects ExtendScript로 내보내기
npx opencaptions export captions.cwi.json --format ae-json
# Premiere Pro XML로 내보내기
npx opencaptions export captions.cwi.json --format premiere-xml
# 시스템 종속성 확인
npx opencaptions doctor
# Python 종속성 설치
npx opencaptions setup
MCP 서버 사용법
OpenCaptions MCP 서버는 에이전트 통합을 위한 네 가지 도구를 제공합니다:
| 도구 | 설명 |
|---|---|
generate_captions | 비디오 파일에서 전체 파이프라인 실행 |
validate_captions | 12개 규칙에 대해 CWI 문서 검증 |
preview_captions | 특정 시간의 터미널 형식 미리보기 |
export_captions | WebVTT 형식으로 내보내기 |
Claude Code를 통해 사용하려면 MCP 서버를 설정에 추가하십시오:
{
"mcpServers": {
"opencaptions": {
"command": "npx",
"args": ["@opencaptions/mcp"]
}
}
}
그런 다음 대화에서 호출하십시오: "Generate CWI captions for video.mp4"가 generate_captions를 트리거합니다.
compose-video.py 통합
Content Engine의 compose-video.py는 --captions 플래그를 허용합니다:
python3 scripts/compose-video.py storyboard.md --brand arcan-studio --captions
--captions가 전달되면 모든 클립이 생성되고 연결된 후 파이프라인은 다음을 수행합니다:
npx opencaptions generate {final-video}.mp4 --output {output-dir}/captions.cwi.json실행- CWI 문서 검증 (점수 < 80이면 경고하지만 차단하지 않음)
--remotion도 전달된 경우, CWI JSON을 Remotion 구성에<CaptionOverlay>props로 삽입- 그렇지 않으면 최종 비디오와 함께 사이드카 파일로 WebVTT 생성
OpenCaptions가 설치되지 않은 경우(npx opencaptions doctor 실패), 파이프라인은 우아하게 저하됩니다:
- 장면 브리프 텍스트 오버레이(스토리보드
## Shot설명의 정적 텍스트)로 폴백 - "OpenCaptions를 사용할 수 없습니다. 장면 브리프 텍스트 오버레이를 사용합니다." 경고 로그
- 클립 경계에서 파생된 타이밍으로
.vtt파일을 계속 생성
자막 스타일
구성을 통해 선택 가능한 세 가지 내장 자막 스타일 프리셋:
1. 단어별 (brainrot)
높은 유지율 스타일: 각 단어가 개별적으로 중앙에 나타나며 최대 크기 변동이 있습니다. 도파민 후크에 최적화된 소셜/TikTok/Reels 콘텐츠에 사용됩니다.
- 한 번에 하나의 단어 표시
- 큰 기본 크기 (1080p에서 64px)
- 극단적인 두께 변동 (100-900 전체 범위)
- 강조 단어는 글로우와 함께 1.5x로 확장
- 배경: 없음 (단어가 비디오 위에 뜸)
- 글꼴: Roboto Flex 가변
2. 내러티브 (편집)
단어별 스타일링으로 전체 문장 표시. 장편 콘텐츠, 다큐멘터리, 블로그 비디오 임베드에 사용됩니다.
- 전체 자막 이벤트 표시, 단어가 인라인으로 스타일링됨
- 중간 기본 크기 (1080p에서 48px)
- 적당한 두께 변동 (300-700)
- 강조 단어는 미묘한 크기 증가 (1.15x)
- 배경: 반투명 알약 (rgba(0,0,0,0.6))
- 글꼴: Roboto Flex 가변
3. 미니멀 (하단 3분)
깔끔한 하단 3분 프레젠테이션. 화자 이름 + 텍스트. 최소한의 시각적 방해. 인터뷰, 토크 헤드, 컨퍼런스 녹화에 사용됩니다.
- 화자 이름 레이블은 화자 색상, 자막 텍스트는 흰색
- 작은 기본 크기 (1080p에서 36px)
- 강조에만 두께 변동 (기본 400, 강조 700)
- 크기 변동 없음
- 배경: 그라데이션 바 (프레임 하단 15%)
- 글꼴: 시스템 산세리프
데이터 계약
읽기 (불변)
- 이전 포스트 프로덕션 단계의 그레이딩된 비디오 에셋
knowledge/compiled/brands/{brand_slug}.md-- 자막 색상 팔레트 및 타이포그래피 기본 설정용- 장면 브리프 (런타임 매개변수) -- 의도된 감정 톤에 대한 컨텍스트용
쓰기 (자체 네임스페이스만)
extensions/opencaptions/output/{asset_id}.cwi.json-- CWI 문서extensions/opencaptions/output/{asset_id}.vtt-- WebVTT 폴백extensions/opencaptions/output/{asset_id}-report.json-- 검증 보고서extensions/opencaptions/output/{asset_id}-captioned.mp4-- 렌더링된 비디오 (Remotion 경로만)
구성
opencaptions:
# 자막 스타일 프리셋
style: "narrative" # word-by-word | narrative | minimal
# 시각 매개변수
font_family: "Roboto Flex" # 가변 폰트 (가변 축용)
base_font_size: 48 # 1080p에서 픽셀
position: "bottom" # top | center | bottom
max_chars_per_line: 42 # FCC 준수
background: "pill" # pill | shadow | gradient | none
background_opacity: 0.6 # 0.0 - 1.0
# 파이프라인 백엔드
backend: "av" # av (V1) | jepa (V2) | tribe (V3)
language: "en" # 전사를 위한 ISO 639-1 힌트
# 화자 재정의 (선택 사항, 기본적으로 자동 감지)
speakers:
- name: "Narrator"
color: "#6B8AFF"
- name: "Guest"
color: "#FF6B6B"
# 렌더링
render_mode: "remotion" # remotion | ffmpeg | sidecar-only
output_format: "mp4" # mp4 | webm
fps: 30 # 원본 비디오와 일치
# 검증
min_score: 80 # 진행을 위한 최소 전체 점수
fail_on_low_score: false # true인 경우 낮은 점수에서 파이프라인 차단
# TRIBE v2 신경망 매핑 (V3 백엔드 전용)
neural_mapping: false # 예측된 신경 반응 스타일링 활성화
우아한 저하
확장은 Content Engine 파이프라인을 절대 차단하지 않습니다. 저하 사다리:
| 조건 | 동작 |
|---|---|
| OpenCaptions CLI 설치됨 + 모든 Python 종속성 | 전체 CWI 파이프라인 (전사, 화자 분리, 의도, 매핑) |
| OpenCaptions CLI 설치됨, Python 종속성 없음 | 플레이스홀더 자막 + 검증이 포함된 모의 백엔드 |
| OpenCaptions CLI 설치되지 않음 | 클립 경계에서 정적 자막으로 장면 브리프 텍스트 오버레이 |
| 비디오에 오디오 트랙 없음 | 자막 생성 건너뛰기, 정보 메시지 로그 |
| 검증 점수 < 80 | 경고하지만 진행 (fail_on_low_score: true인 경우 제외) |
| Remotion 사용 불가 | ffmpeg ASS burn-in으로 폴백 |
| ffmpeg 사용 불가 | CWI JSON + WebVTT만 사이드카로 출력 (렌더링된 비디오 없음) |
관련
- OpenCaptions 프로젝트:
~/broomva/apps/opencaptions/ - CWI-Remotion 브리지:
references/cwi-remotion-bridge.md - 통합 가이드:
references/integration-guide.md - Content Engine SKILL.md:
../../SKILL.md - 확장 프레임워크:
../README.md