SpotMaster_v1.0 / core /video_editor.py
Marek4321's picture
Create video_editor.py
bf72d61 verified
# @title core/video_editor.py
import os
import json
import asyncio
from typing import List, Dict, Any, Optional
from pathlib import Path
import subprocess
from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_videoclips
from utils.logger import SpotMakerLogger
class VideoEditor:
"""
Montażysta video który łączy wygenerowane klipy z audio w finalny spot.
"""
def __init__(self, output_dir: str, logger: SpotMakerLogger):
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.logger = logger
async def create_spot(self, video_paths: List[str], audio_path: str, audio_duration: float) -> str:
"""
Tworzy finalny spot łącząc klipy video ze ścieżką audio.
Args:
video_paths: Lista ścieżek do klipów video
audio_path: Ścieżka do pliku audio
audio_duration: Długość ścieżki audio w sekundach
Returns:
Ścieżka do finalnego spotu
"""
try:
self.logger.log("video_editor", "Rozpoczynam montaż spotu", "info")
self.logger.update_progress("video_editor", 0, "Inicjalizacja...")
# Oblicz długość pojedynczego klipu
clip_duration = audio_duration / len(video_paths)
self.logger.log("video_editor",
f"Długość pojedynczego klipu: {clip_duration:.2f}s",
"debug")
# Wczytaj i przygotuj klipy
clips = []
for i, path in enumerate(video_paths, 1):
self.logger.update_progress("video_editor",
i * 20,
f"Przetwarzam klip {i}/{len(video_paths)}")
self.logger.log("video_editor", f"Wczytuję klip: {path}", "debug")
clip = VideoFileClip(path)
# Dostosuj długość klipu
if clip.duration != clip_duration:
clip = clip.set_duration(clip_duration)
clips.append(clip)
# Połącz klipy
self.logger.update_progress("video_editor", 80, "Łączę klipy...")
final_video = concatenate_videoclips(clips)
# Dodaj ścieżkę audio
self.logger.update_progress("video_editor", 90, "Dodaję audio...")
audio = AudioFileClip(audio_path)
final_video = final_video.set_audio(audio)
# Zapisz finalny spot
output_path = self.output_dir / "final_spot.mp4"
self.logger.log("video_editor",
f"Zapisuję finalny spot: {output_path}",
"debug")
final_video.write_videofile(
str(output_path),
codec='libx264',
audio_codec='aac',
temp_audiofile='temp-audio.m4a',
remove_temp=True
)
# Zamknij klipy aby zwolnić zasoby
final_video.close()
audio.close()
for clip in clips:
clip.close()
self.logger.update_progress("video_editor", 100, "Montaż zakończony")
return str(output_path)
except Exception as e:
self.logger.format_error("video_editor", e)
raise
def get_status(self) -> Dict[str, Any]:
"""Zwraca aktualny status montażysty."""
return {
'progress': self.logger.get_module_progress("video_editor"),
'status': self.logger.get_module_status("video_editor")
}