vibe-writer / src /BE /export_utils.py
psvm203's picture
feat: add vibe-writer sources
f89ae58
Raw
History Blame Contribute Delete
1.78 kB
import subprocess
import os
def merge_video(frames_dir, audio_path, output_name="output.mp4"):
"""
์ด๋ฏธ์ง€ ํ”„๋ ˆ์ž„๋“ค๊ณผ ์˜ค๋””์˜ค ํŒŒ์ผ์„ ํ•˜๋‚˜๋กœ ํ•ฉ์น˜๋Š” ํ•จ์ˆ˜
:param frames_dir: ์ด๋ฏธ์ง€ ํŒŒ์ผ๋“ค์ด ๋“ค์–ด์žˆ๋Š” ํด๋” ๊ฒฝ๋กœ
:param audio_path: ํ•ฉ์„ฑํ•  ์˜ค๋””์˜ค ํŒŒ์ผ ๊ฒฝ๋กœ
:param output_name: ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ ํŒŒ์ผ ์ด๋ฆ„
"""
# 1. ์ด๋ฏธ์ง€ ํŒŒ์ผ ํŒจํ„ด ์„ค์ • (์˜ˆ: frame_0001.png, frame_0002.png ...)
image_pattern = os.path.join(frames_dir, "frame_%04d.png")
# 2. FFmpeg ๋ช…๋ น์–ด ๊ตฌ์„ฑ
command = [
'ffmpeg',
'-y', # ๊ธฐ์กด ํŒŒ์ผ์ด ์žˆ์œผ๋ฉด ๋ฎ์–ด์“ฐ๊ธฐ
'-framerate', '30', # ์ดˆ๋‹น ํ”„๋ ˆ์ž„ ์ˆ˜ (FPS)
'-i', image_pattern, # ์ž…๋ ฅ ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
'-i', audio_path, # ์ž…๋ ฅ ์˜ค๋””์˜ค ๊ฒฝ๋กœ
'-c:v', 'libx264', # ๋น„๋””์˜ค ์ฝ”๋ฑ (H.264)
'-pix_fmt', 'yuv420p', # ๋Œ€๋ถ€๋ถ„์˜ ์žฌ์ƒ๊ธฐ์—์„œ ์ง€์›ํ•˜๋Š” ํ”ฝ์…€ ํฌ๋งท
'-c:a', 'aac', # ์˜ค๋””์˜ค ์ฝ”๋ฑ (AAC)
'-shortest', # ์˜์ƒ/์˜ค๋””์˜ค ์ค‘ ์งง์€ ์ชฝ์— ๋งž์ถค
output_name # ์ตœ์ข… ํŒŒ์ผ๋ช…
]
try:
# 3. ๋ช…๋ น์–ด ์‹คํ–‰
print(f"ํ•ฉ์„ฑ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค: {output_name}")
subprocess.run(command, check=True)
print("ํ•ฉ์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!")
except subprocess.CalledProcessError as e:
print(f"ํ•ฉ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
except FileNotFoundError:
print("FFmpeg๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ฒฝ๋กœ ์„ค์ •์„ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.")
# ์‚ฌ์šฉ ์˜ˆ์‹œ (๋‚˜์ค‘์— ์‹ค์ œ ๊ฒฝ๋กœ๋กœ ์ˆ˜์ •)
# merge_video("./frames", "./background_music.mp3")