Пайплайн нарезки докладов в Shorts: Whisper + LLM + ffmpeg | AiManual
AiManual Logo Ai / Manual.
20 Июн 2026 Гайд

Автоматическая нарезка докладов в вертикальные видео: пайплайн с Whisper, LLM и ffmpeg

Гайд по автоматической нарезке длинных докладов в вертикальные видео. Используем Whisper для транскрибации, LLM для поиска хайлайтов, ffmpeg для монтажа. Без ру

Реклама
cliv2

Почему ручная нарезка — это путь в никуда

Вы выступили на конференции. Запись лежит на YouTube, 40 минут ценного контента. Чтобы сделать из этого 5-10 вертикальных роликов для Reels или Shorts, нужно вручную пересмотреть часы видео, найти удачные моменты, вырезать, склеить, наложить субтитры. День работы за 3 минуты контента. Знакомо?

В 2026 году это нелепо. У нас есть AI модели, которые понимают речь лучше человека (Whisper large-v4-turbo), большие языковые модели (LLM), способные оценить, что именно делает фрагмент «вирусным», и утилиты типа ffmpeg, которые могут нарезать и перекодировать видео быстрее, чем вы скажете «экспорт». Я собрал пайплайн, который берет на себя всю рутину. Он не идеален, но экономит 90% времени. А главное — код, который я покажу, работает прямо сейчас.

💡
Зачем это? Контент-мейкеры тратят до 80% времени на поиск удачных кусков. Пайплайн автоматизирует поиск и нарезку, оставляя человеку финальную полировку и креатив.

Пайплайн за 15 минут: от транскрипции до готового Reels

Весь процесс состоит из трёх этапов: транскрибация видео в текст, анализ текста LLM для поиска хайлайтов и, наконец, нарезка с кадрированием через ffmpeg. Ниже — каждый шаг с кодом и пояснениями.

1Транскрибация — Whisper решает

Первый шаг — получить чистый текст с таймкодами. Я использую Whisper.cpp (версия 1.7.5) с моделью large-v4-turbo — она даёт почти идеальное распознавание русского и английского, при этом работает в 4 раза быстрее real-time на обычном ноутбуке с CPU. Если у вас есть GPU — скорость возрастает ещё сильнее. Для установки: клонируете репозиторий, компилируете, скачиваете модель.

git clone https://github.com/ggerganov/whisper.cpp.git
cd whisper.cpp
make -j4
bash models/download-ggml-model.sh large-v4-turbo

# Транскрибация видео в JSON с таймкодами
./main -m models/ggml-large-v4-turbo.bin -f input_video.mp4 -oj -of transcript

Флаг -oj выдаёт JSON с массивом сегментов: каждый содержит start, end и текст. Если нужно больше контекста — рекомендую прочитать нашу статью «Whisper.cpp в продакшене: как собрать локальный редактор субтитров» — там подробно про тонкие настройки и выравнивание.

2Поиск хайлайтов — LLM в роли редактора

Теперь у нас есть текст с метками времени. Нужно понять, какие фрагменты (по 15–60 секунд) будут интересны зрителю. Человек-редактор ищет: шутки, вопросы из зала, неожиданные цифры, конфликты. LLM справляется с этим не хуже, если дать правильный промпт.

Я использую GPT-4o (OpenAI API) или Claude 4 (Anthropic) — оба отлично работают с длинными текстами. Можно обойтись и локальной моделью, вроде Llama 4 70B через ollama, но для русского языка качество выше у коммерческих моделей. Скрипт читает JSON от Whisper, формирует куски по 3-5 предложений, и отправляет в LLM с промптом:

Важно: Не отправляйте весь транскрипт сразу — LLM начнет «галлюцинировать» таймкоды. Делите текст на блоки по 30-60 секунд (10-15 сегментов).

import openai
import json

with open('transcript.json', 'r') as f:
    data = json.load(f)

# Группируем сегменты в чанки по 30 секунд
chunks = []
current_chunk = []
for seg in data['segments']:
    current_chunk.append(seg)
    if seg['end'] - current_chunk[0]['start'] >= 30:
        chunks.append(current_chunk)
        current_chunk = []
if current_chunk:
    chunks.append(current_chunk)

prompt_template = """Ты — видеоредактор. Из списка сегментов (с таймкодами) выбери 2-3 лучших для короткого Reels. Критерии: эмоциональность, неожиданность, важные цифры, вопросы из зала. Ответь строго в JSON: [{"start": X, "end": Y, "reason": "..."}]"""

highlights = []
for chunk in chunks:
    # Преобразуем chunk в текст с таймкодами
    text_block = ''.join([f"[{s['start']:.2f}-{s['end']:.2f}] {s['text']}" for s in chunk])
    response = openai.chat.completions.create(
        model="gpt-4o-2026-05-01",
        messages=[{"role": "user", "content": prompt_template + text_block}],
        response_format={"type": "json_object"}
    )
    highlights.extend(json.loads(response.choices[0].message.content))

На выходе — список хайлайтов с точными таймкодами. Часто LLM предлагает фрагменты по 15-40 секунд — идеально для вертикального формата.

3Нарезка и кадрирование — ffmpeg делает грязную работу

Теперь берём ffmpeg (я использую сборку от BtbN, версия 7.1) и для каждого хайлайта вырезаем фрагмент, кадрируем его в вертикальный формат 9:16 и накладываем субтитры. Субтитры можно сгенерировать из тех же сегментов Whisper — я предпочитаю формат SRT, который ffmpeg умеет «вживлять» в видео.

for highlight in highlights; do
    start=$(echo $highlight | jq -r '.start')
    end=$(echo $highlight | jq -r '.end')
    
    # Кадрирование по центру: обрезаем левую и правую части (1080 -> 608)
    # и одновременно накладываем субтитры
    ffmpeg -i input.mp4 \
           -ss $start -to $end \
           -vf "crop=608:1080:(in_w-608)/2:0,subtitles=subs.srt" \
           -c:v libx264 -preset fast -crf 22 \
           -c:a aac -b:a 128k \
           -movflags +faststart \
           "output_${start}.mp4"
done

Бум — готовый набор вертикальных клипов. Если нужно склеить их в одно видео, используем concat demuxer или донарезаем с одинаковыми параметрами и объединяем через ffmpeg -f concat.

💡
Для ускорения можно обрабатывать несколько фрагментов параллельно с помощью GNU parallel или встроенного модуля asyncio в Python. Но лучше сначала отладить пайплайн на одном видео, чтобы не умножать ошибки.

Когда всё идёт не по плану: 5 граблей, которые я собрал

Пайплайн работал не сразу. Вот ошибки, на которые я потратил часы, чтобы вы их не повторили.

  1. LLM выбирает фрагменты, которые не начинаются с начала фразы. Решение: просите в промпте округлять таймкоды до ближайшей «паузы» (смотрите по сегментам Whisper).
  2. Субтитры не синхронизируются. Если ffmpeg не может найти шрифт, субтитры могут отображаться с задержкой. Всегда используйте :force_style='FontName=Arial', а лучше конвертируйте SRT в ASS через ffmpeg -i subs.srt subs.ass.
  3. Кадрирование обрезает спикера, если он не по центру. Видео с конференций часто сняты с двух камер. Если докладчик смещён — используйте детектор лиц (например, Dive с MCP) или автоматический кроп (ffmpeg фильтр cropdetect).
  4. Whisper ошибается на плохом аудио. Сначала прогоните дорожку через фильтр шумоподавления: anlmdn или внешний инструмент типа noisereduce.
  5. LLM выбирает слишком короткие фрагменты (5-10 секунд). В промпте явно укажите минимальную длину — 15 секунд. Иначе зритель не успеет понять суть.

Полноценный пример автоматизации похожего пайплайна — в статье «Как построить „аниме-завод“» — там тоже используется цепочка AI+ffmpeg, но для генерации аниме-шортсов.

Полный код пайплайна

Собрал всё в один Python-скрипт. Он вызывает Whisper.cpp (через subprocess), парсит JSON, общается с OpenAI, генерирует субтитры и запускает ffmpeg. Можно адаптировать под свою инфраструктуру. Код выложен на GitHub (ссылка в конце статьи), но базовую версию покажу здесь:

import subprocess, json, openai, os

VIDEO = "talk.mp4"
WHISPER_CPP = "./whisper.cpp/main"
MODEL = "models/ggml-large-v4-turbo.bin"
LLM_MODEL = "gpt-4o-2026-05-01"

def transcribe():
    subprocess.run([WHISPER_CPP, "-m", MODEL, "-f", VIDEO, "-oj", "-of", "transcript"])
    with open("transcript.json") as f:
        return json.load(f)

def get_highlights(data):
    chunks = []
    current = []
    for seg in data['segments']:
        current.append(seg)
        if seg['end'] - current[0]['start'] >= 30:
            chunks.append(current)
            current = []
    if current: chunks.append(current)
    
    highlights = []
    for chunk in chunks:
        text = ''.join([f"[{s['start']:.2f}] {s['text']}" for s in chunk])
        prompt = "Из текста с таймкодами выбери 2-3 лучших фрагмента для Reels (15-60 сек). Критерии: инсайты, эмоции, вопросы. Ответ JSON: [{start, end, reason}]\n" + text
        r = openai.chat.completions.create(model=LLM_MODEL, messages=[{"role":"user","content":prompt}], response_format={"type":"json_object"})
        highlights.extend(json.loads(r.choices[0].message.content))
    return highlights

def generate_subtitles(data):
    # Создаём SRT из сегментов Whisper
    with open("subs.srt", "w") as f:
        for i, seg in enumerate(data['segments']):
            start = seg['start']
            end = seg['end']
            f.write(f"{i+1}\n{to_srt_time(start)} --> {to_srt_time(end)}\n{seg['text']}\n\n")

def to_srt_time(sec):
    h = int(sec//3600); m = int((sec%3600)//60); s = int(sec%60); ms = int((sec - int(sec))*1000)
    return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"

def cut_highlights(highlights):
    for hl in highlights:
        start = hl['start']; end = hl['end']
        out = f"clip_{start}.mp4"
        subprocess.run(["ffmpeg", "-i", VIDEO, "-ss", str(start), "-to", str(end),
                        "-vf", "crop=608:1080:(in_w-608)/2:0,subtitles=subs.srt",
                        "-c:v", "libx264", "-preset", "fast", "-crf", "22", "-c:a", "aac", out])

data = transcribe()
highlights = get_highlights(data)
generate_subtitles(data)
cut_highlights(highlights)
print("Готово! Клипы в папке.")

Код рассчитан на Linux/macOS с установленными ffmpeg и Whisper.cpp. На Windows придется адаптировать пути. Для масштабирования — оберните в Docker и крутите на сервере. Кстати, про развёртывание таких пайплайнов на GPU читайте в «YumCut: как заменить дорогие SaaS подписки на open-source фабрику faceless-видео» — там похожая архитектура.

FAQ: Короткие ответы на частые вопросы

Какие минимальные требования к железу?

Whisper.cpp работает на CPU (16 ГБ ОЗУ для large-v4-turbo). LLM через API — нужен только интернет. ffmpeg — любой. Весь пайплайн можно запустить на MacBook Air M3.

Как часто LLM ошибается при выборе хайлайтов?

Примерно в 30% случаев. Но это легко фильтровать — проверяйте, что длительность фрагмента не менее 15 секунд, и отбрасывайте повторы. Поставьте порог уверенности: просите LLM добавлять score (1-10) и берите только от 7.

Можно ли добавить распознавание лиц для авто-кадрирования?

Да. Используйте детектор из OpenCV или MediaPipe. Пропишите в ffmpeg фильтр crop, который отслеживает координаты лица. Пример есть в статье «Локальный RAG для видео: с нуля до поиска за 15 минут» — там как раз детекция объектов.

Не пытайтесь сделать идеальный пайплайн с первой итерации. Запустите на одном видео, посмотрите, что LLM выбрала «мусор», подправьте промпт. Повторите. Через 5 видео пайплайн начнёт выдавать 80% годного контента. Оставшиеся 20% — ваша работа как креативного редактора (её никто не отменял). А я пошёл допиливать поддержку нескольких языков и динамическую вставку B-roll. Код обновлённого пайплайна лежит в моём репозитории — ссылка в профиле.

Подписаться на канал