111 lines
4.4 KiB
Python
111 lines
4.4 KiB
Python
import os
|
|
from moviepy.editor import VideoFileClip, concatenate_videoclips
|
|
import tempfile
|
|
from datetime import datetime
|
|
from core.logger import Logger
|
|
|
|
|
|
class VideoProcessor:
|
|
def __init__(self):
|
|
self.logger = Logger()
|
|
|
|
def process_videos(self, video_data, output_dir, output_format="mp4",
|
|
quality="high", progress_callback=None):
|
|
"""
|
|
Основной метод обработки видео
|
|
"""
|
|
self.logger.log("INFO", f"Начало обработки {len(video_data)} видео файлов")
|
|
|
|
clips = []
|
|
total_steps = sum(len(data['time_ranges']) for data in video_data) + 2
|
|
current_step = 0
|
|
|
|
try:
|
|
# Обработка каждого видео файла
|
|
for i, data in enumerate(video_data):
|
|
video_path = data['path']
|
|
time_ranges = data['time_ranges']
|
|
|
|
self.logger.log("INFO", f"Обработка файла: {os.path.basename(video_path)}")
|
|
|
|
with VideoFileClip(video_path) as video:
|
|
# Вырезаем указанные диапазоны
|
|
for start, end in time_ranges:
|
|
if progress_callback:
|
|
progress = current_step / total_steps
|
|
progress_callback(progress,
|
|
f"Вырезание фрагмента {i + 1}/{len(video_data)}")
|
|
|
|
# Обрезаем видео по таймкодам
|
|
clip = video.subclip(start, end)
|
|
clips.append(clip)
|
|
current_step += 1
|
|
|
|
self.logger.log("INFO",
|
|
f"Вырезан фрагмент: {self.format_time(start)} - {self.format_time(end)}")
|
|
|
|
if not clips:
|
|
raise ValueError("Нет видео фрагментов для объединения")
|
|
|
|
# Объединение клипов
|
|
if progress_callback:
|
|
progress_callback(current_step / total_steps, "Объединение видео фрагментов")
|
|
|
|
self.logger.log("INFO", f"Объединение {len(clips)} фрагментов")
|
|
final_clip = concatenate_videoclips(clips)
|
|
|
|
# Настройка качества
|
|
bitrate = self.get_bitrate(quality)
|
|
|
|
# Генерация имени выходного файла
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
output_filename = f"edited_video_{timestamp}.{output_format}"
|
|
output_path = os.path.join(output_dir, output_filename)
|
|
|
|
# Сохранение результата
|
|
if progress_callback:
|
|
progress_callback((total_steps - 1) / total_steps, "Сохранение итогового файла")
|
|
|
|
self.logger.log("INFO", f"Сохранение файла: {output_path}")
|
|
final_clip.write_videofile(
|
|
output_path,
|
|
codec='libx264',
|
|
bitrate=bitrate,
|
|
audio_codec='aac',
|
|
verbose=False,
|
|
logger=None
|
|
)
|
|
|
|
# Закрытие клипов
|
|
final_clip.close()
|
|
for clip in clips:
|
|
clip.close()
|
|
|
|
self.logger.log("SUCCESS", f"Обработка завершена успешно: {output_path}")
|
|
return output_path
|
|
|
|
except Exception as e:
|
|
self.logger.log("ERROR", f"Ошибка обработки: {str(e)}")
|
|
# Закрытие клипов в случае ошибки
|
|
for clip in clips:
|
|
try:
|
|
clip.close()
|
|
except:
|
|
pass
|
|
raise
|
|
|
|
def get_bitrate(self, quality):
|
|
"""Определение битрейта в зависимости от качества"""
|
|
quality_settings = {
|
|
'low': '1000k',
|
|
'medium': '3000k',
|
|
'high': '8000k'
|
|
}
|
|
return quality_settings.get(quality, '3000k')
|
|
|
|
def format_time(self, seconds):
|
|
"""Форматирование времени в читаемый вид"""
|
|
hours = int(seconds // 3600)
|
|
minutes = int((seconds % 3600) // 60)
|
|
seconds = int(seconds % 60)
|
|
return f"{hours:02d}:{minutes:02d}:{seconds:02d}" |