File size: 2,965 Bytes
fc15bf4
ba0f6a0
 
 
 
 
fc15bf4
 
 
 
 
ba0f6a0
 
 
 
 
 
 
 
 
fc15bf4
ba0f6a0
 
 
 
 
fc15bf4
ba0f6a0
 
 
 
 
fc15bf4
ba0f6a0
 
 
 
 
 
fc15bf4
ba0f6a0
 
 
 
 
 
 
 
 
 
 
 
 
fc15bf4
ba0f6a0
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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