51 lines
1.9 KiB
Python
51 lines
1.9 KiB
Python
"""render 수동 확인용.
|
|
|
|
사용: uv run python -m tests.poster_alive.test_render <포스터경로> [클립경로]
|
|
클립을 생략하면 test_result/<이름>.clip.mp4 를 쓴다.
|
|
나레이션(.tts.mp3)·타임라인(.tts.txt)·BGM(.bgm.mp3)은 있으면 얹고 없으면 건너뛴다.
|
|
결과는 <이름>.final.mp4 와 <이름>.thumb.jpg.
|
|
"""
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from models.tts import NarrationTimeline
|
|
from services.render import render
|
|
|
|
TEST_RESULT_DIR = Path(__file__).parent.parent / "test_result" / "poster_alive"
|
|
|
|
|
|
def read_if_exists(path: Path) -> bytes | None:
|
|
return path.read_bytes() if path.exists() else None
|
|
|
|
|
|
def main() -> None:
|
|
poster_path = Path(sys.argv[1])
|
|
output_base = TEST_RESULT_DIR / poster_path.stem
|
|
clip_path = Path(sys.argv[2]) if len(sys.argv) > 2 else output_base.with_suffix(".clip.mp4")
|
|
if not clip_path.exists():
|
|
raise SystemExit(f"클립 없음: {clip_path}")
|
|
|
|
timeline_path = output_base.with_suffix(".tts.txt")
|
|
timeline = (NarrationTimeline.model_validate_json(timeline_path.read_text(encoding="utf-8"))
|
|
if timeline_path.exists() else None)
|
|
narration = read_if_exists(output_base.with_suffix(".tts.mp3"))
|
|
bgm = read_if_exists(output_base.with_suffix(".bgm.mp3"))
|
|
print(f"클립 {clip_path.name} / 나레이션 {'있음' if narration else '없음'}"
|
|
f" / BGM {'있음' if bgm else '없음'}")
|
|
|
|
result = render(clip_path.read_bytes(), poster_path,
|
|
narration=narration, bgm=bgm, timeline=timeline)
|
|
|
|
video_path = output_base.with_suffix(".final.mp4")
|
|
thumb_path = output_base.with_suffix(".thumb.jpg")
|
|
video_path.write_bytes(result.video)
|
|
thumb_path.write_bytes(result.thumbnail)
|
|
|
|
print(f"{result.width}x{result.height} · {result.frames}프레임 · {result.duration:.2f}초 "
|
|
f"· {len(result.video) / 1e6:.1f}MB")
|
|
print(f"\n{video_path}\n{thumb_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|