Разработка системы AI-автомонтажа видео
AI-автомонтаж обрабатывает исходный видеоматериал: нарезает по ключевым моментам, подбирает музыку, добавляет субтитры, применяет переходы и цветокоррекцию. Заменяет 60–80% ручной работы видеомонтажёра при создании highlight-роликов, коротких клипов, recap-контента.
Архитектура пайплайна
from dataclasses import dataclass, field
from typing import Optional
import asyncio
@dataclass
class VideoSegment:
start_time: float
end_time: float
transcript: str
emotion_score: float # 0–1, насколько эмоционально
action_score: float # 0–1, насколько динамично
quality_score: float # 0–1, техническое качество
selected: bool = False
class AutoVideoEditor:
def __init__(self):
self.scene_detector = SceneDetector()
self.transcriber = WhisperTranscriber()
self.emotion_analyzer = EmotionAnalyzer()
self.music_selector = MusicSelector()
self.renderer = VideoRenderer()
async def create_highlight_reel(
self,
source_video: str,
target_duration: int = 60, # секунды
style: str = "dynamic" # dynamic, calm, corporate, emotional
) -> str:
# 1. Нарезаем на сцены
scenes = self.scene_detector.detect(source_video)
# 2. Транскрибируем + оцениваем каждую сцену
scored_scenes = await self.score_scenes(scenes, source_video)
# 3. Отбираем лучшие сцены под target_duration
selected = self.select_scenes(scored_scenes, target_duration, style)
# 4. Монтируем финальное видео
return await self.renderer.render(
source_video, selected,
transitions=True,
color_grade=style
)
Обнаружение сцен
import cv2
import numpy as np
from scenedetect import open_video, SceneManager
from scenedetect.detectors import ContentDetector
class SceneDetector:
def detect(self, video_path: str, threshold: float = 27.0) -> list[dict]:
video = open_video(video_path)
scene_manager = SceneManager()
scene_manager.add_detector(ContentDetector(threshold=threshold))
scene_manager.detect_scenes(video)
scene_list = scene_manager.get_scene_list()
return [
{
"start": scene[0].get_seconds(),
"end": scene[1].get_seconds(),
"duration": scene[1].get_seconds() - scene[0].get_seconds()
}
for scene in scene_list
]
AI-оценка качества сцены
from openai import AsyncOpenAI
import base64
client = AsyncOpenAI()
async def score_scene_with_gpt4v(
video_path: str,
start: float,
end: float,
transcript: str
) -> dict:
"""Оцениваем сцену через GPT-4 Vision на основе ключевых кадров"""
# Извлекаем средний кадр сцены
import subprocess
mid_time = (start + end) / 2
frame_path = f"/tmp/frame_{int(mid_time*1000)}.jpg"
subprocess.run([
"ffmpeg", "-ss", str(mid_time), "-i", video_path,
"-vframes", "1", "-q:v", "2", frame_path
], capture_output=True)
with open(frame_path, "rb") as f:
frame_b64 = base64.b64encode(f.read()).decode()
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": [
{
"type": "text",
"text": f"""Оцени сцену для включения в highlight-ролик.
Транскрипт: {transcript}
Верни JSON: {{"emotion_score": 0-1, "action_score": 0-1, "quality_score": 0-1, "reason": "..."}}"""
},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{frame_b64}"}}
]
}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
Рендеринг через MoviePy
from moviepy.editor import (
VideoFileClip, concatenate_videoclips,
TextClip, CompositeVideoClip, AudioFileClip,
vfx
)
class VideoRenderer:
def render_highlights(
self,
source_path: str,
segments: list[dict],
output_path: str,
music_path: str = None
) -> str:
clips = []
for seg in segments:
clip = VideoFileClip(source_path).subclip(seg["start"], seg["end"])
# Плавный переход
clip = clip.fadein(0.3).fadeout(0.3)
# Цветокоррекция (лёгкое осветление)
clip = clip.fx(vfx.colorx, 1.05)
clips.append(clip)
final = concatenate_videoclips(clips, method="compose")
if music_path:
music = AudioFileClip(music_path).set_duration(final.duration)
music = music.volumex(0.3)
# Миксуем: оригинальное аудио + музыка
from moviepy.audio.AudioClip import CompositeAudioClip
final = final.set_audio(
CompositeAudioClip([final.audio.volumex(0.8), music])
)
final.write_videofile(output_path, codec="libx264", audio_codec="aac")
return output_path
AI-генерация субтитров и капшенов
async def add_auto_captions(video_path: str, output_path: str, style: str = "social") -> str:
# Транскрибируем с таймингами
result = whisper_model.transcribe(video_path, word_timestamps=True)
clip = VideoFileClip(video_path)
caption_clips = []
for segment in result["segments"]:
txt_clip = TextClip(
segment["text"].upper() if style == "social" else segment["text"],
fontsize=48 if style == "social" else 32,
color="white",
stroke_color="black",
stroke_width=2,
font="Arial-Bold",
method="caption",
size=(clip.w * 0.9, None)
).set_start(segment["start"]).set_end(segment["end"])
txt_clip = txt_clip.set_position(("center", "bottom"))
caption_clips.append(txt_clip)
final = CompositeVideoClip([clip] + caption_clips)
final.write_videofile(output_path, codec="libx264")
return output_path
Сроки: MVP автомонтажа с highlight detection и базовой нарезкой — 2–3 недели. Полноценный редактор с музыкой, субтитрами, цветокоррекцией и несколькими стилями — 2–3 месяца.







