admaker / core /assembler.py
karthikeya1212's picture
Upload 24 files
eb8c5e1 verified
raw
history blame
2.09 kB
# core/assembler.py
"""
Assembler combines video + music and optionally overlays images/text,
and produces final assembled output. Uses ffmpeg for merging audio/video.
Returns a dict with final path and metadata.
"""
import subprocess
import time
from pathlib import Path
from typing import Dict
from config import OUTPUT_DIR
OUTPUT_DIR = Path(OUTPUT_DIR)
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
def assemble_video(video_result: Dict, music_result: Dict, out_name: str = None) -> Dict:
"""
video_result: dict returned from video_generator
music_result: dict returned from music_generator
Returns dict { "final_path":..., "duration":..., "meta":... }
"""
t0 = time.time()
video_path = Path(video_result.get("video_path"))
music_path = Path(music_result.get("music_path"))
out_name = out_name or f"final_{int(time.time()*1000)}.mp4"
out_path = OUTPUT_DIR / out_name
# If ffmpeg is available, merge audio and video
if video_path.exists() and music_path.exists():
cmd = [
"ffmpeg", "-y",
"-i", str(video_path),
"-i", str(music_path),
"-c:v", "copy", # copy video stream
"-c:a", "aac",
"-shortest",
str(out_path)
]
try:
subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
duration = video_result.get("duration", 0.0)
except Exception as e:
print(f"[assembler] ffmpeg merge failed: {e}. Creating placeholder final output.")
with open(out_path, "wb") as f:
f.write(b"")
duration = 0.0
else:
# If audio or video missing, create a placeholder
with open(out_path, "wb") as f:
f.write(b"")
duration = 0.0
meta = {
"video_src": str(video_path),
"music_src": str(music_path),
"assembled_at": time.time() - t0
}
return {"final_path": str(out_path), "duration": duration, "meta": meta}