# renderer.py import cv2 import tempfile import subprocess import numpy as np from PIL import Image, ImageDraw # ИСПРАВЛЕНО: Заменены слэши на точки и убрана папка visualizer from effects.particles import ParticleEffect from effects.text import ScrollingTextEffect from effects.spectrum import SpectrumEffect from effects.camera import AICameraEffect class VideoRenderer: def __init__(self, width, height, fps, base_texture, audio_features, user_settings): self.width = width self.height = height self.fps = fps self.base_texture = base_texture.resize((width, height), Image.LANCZOS) self.audio_features = audio_features self.settings = user_settings self.effects = [] if self.settings['enable_particles']: self.effects.append(ParticleEffect(width, height)) if self.settings['enable_spectrum']: self.effects.append(SpectrumEffect(width, height)) text = f"{self.settings.get('artist', '')} - {self.settings.get('title', '')}".strip(" -") if text: self.effects.append(ScrollingTextEffect(text, width, height)) self.camera_effect = AICameraEffect(width, height) if self.settings['enable_camera_effect'] else None def render(self, audio_path): duration = min(self.settings['duration'], self.audio_features['duration']) total_frames = int(duration * self.fps) video_path = tempfile.mktemp(suffix=".mp4") out = cv2.VideoWriter(video_path, cv2.VideoWriter_fourcc(*'mp4v'), self.fps, (self.width, self.height)) for i in range(total_frames): current_time = i / self.fps frame = self.base_texture.copy().convert("RGBA") if self.camera_effect: frame = self.camera_effect.draw(frame, current_time, self.audio_features) draw = ImageDraw.Draw(frame, 'RGBA') for effect in self.effects: effect.draw(draw, current_time, self.audio_features) cv_frame = cv2.cvtColor(np.array(frame), cv2.COLOR_RGBA2BGR) out.write(cv_frame) out.release() print("Рендеринг видео завершен. Добавление аудио...") final_video_path = self.mux_audio_video(video_path, audio_path, duration) return final_video_path def mux_audio_video(self, video_path, audio_path, duration): final_path = tempfile.mktemp(suffix="_final.mp4") cmd = ['ffmpeg', '-y', '-i', video_path, '-i', audio_path, '-c:v', 'copy', '-c:a', 'aac', '-map', '0:v:0', '-map', '1:a:0', '-t', str(duration), final_path] try: subprocess.run(cmd, check=True, capture_output=True, text=True) print("Аудио успешно добавлено.") return final_path except subprocess.CalledProcessError as e: print(f"FFMPEG Ошибка: {e.stderr}") return video_path