capcut-agent/build_letterbox.py
hehihoho3@gmail.com bf1b387d6d chore: git 저장소 초기화 (기존 코드 스냅샷)
컷별 댓글 추천 작업을 태스크 단위로 되돌릴 수 있게 버전관리를 시작한다.
.gitignore 로 영상·캐시(.downloads 2.7G, .comments 72M, .media 28M)와
비밀키(.gemini_key)를 제외했다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 11:36:05 +09:00

73 lines
2.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""레터박스 CLI: 미리 잘라둔 클립 → 무음 컷 + 자막 + 9:16 검은 띠 드래프트.
사용:
python build_letterbox.py <video> [draft_name]
처리:
1. 영상을 9:16 레터박스(가로영상 중앙 + 위아래 검은 띠) h264 mp4 로 굽기(.media/)
2. 전사(캐시) → 발화 세그먼트만 남겨 점프컷 + 세그먼트 자막 동기
3. 캔버스 1080×1920, 레터박스 영상은 scale 1.0(비율 일치) → 크롭/transform 추측 없음
"""
from __future__ import annotations
import os
import sys
import time
from capcut_agent.probe import probe
from capcut_agent.transcribe import transcribe
from capcut_agent.highlight import clips_in_window
from capcut_agent.media import to_letterbox
from capcut_agent.draft import build_shortform_draft
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
MEDIA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".media")
os.makedirs(MEDIA_DIR, exist_ok=True)
def main(argv: list[str]) -> int:
if len(argv) < 2:
print("usage: python build_letterbox.py <video> [name]")
return 2
video = os.path.abspath(argv[1])
if not os.path.isfile(video):
print(f"파일 없음: {video}")
return 2
name = argv[2] if len(argv) > 2 else (
os.path.splitext(os.path.basename(video))[0] + "_레터박스"
)
t0 = time.time()
src_meta = probe(video)
print(f"[probe] {src_meta.width}x{src_meta.height} @ {src_meta.fps}fps, {src_meta.duration:.1f}s")
# 1) 9:16 레터박스 굽기 (전체 클립, 타임라인 보존)
lb_path = os.path.join(MEDIA_DIR, f"{name}.mp4")
to_letterbox(video, lb_path)
lb_meta = probe(lb_path)
print(f"[letterbox] {lb_meta.width}x{lb_meta.height}{lb_path}")
# 2) 전사 → 발화 세그먼트 = 점프컷 + 자막
tr = transcribe(video, model_size="medium", language="ko", use_cache=True)
clips = clips_in_window(tr, 0.0, src_meta.duration)
if not clips:
print("[asr] 발화 세그먼트 없음 — 오디오 확인 필요")
return 1
kept = sum(e - s for s, e, _ in clips)
print(f"[cut] 발화 {len(clips)}구간, {kept:.1f}s (원본 {src_meta.duration:.1f}s, "
f"{src_meta.duration - kept:.1f}s 무음 제거)")
# 3) 드래프트 (레터박스 영상은 9:16 → scale 1.0 자동)
path = build_shortform_draft(lb_path, clips, lb_meta, name, captions=True)
print(f"[draft] {path}")
print(f"[done] {time.time()-t0:.1f}s. CapCut에서 '{name}' 열어 검증.")
return 0
if __name__ == "__main__":
raise SystemExit(main(sys.argv))