Антон Малявский Антон Малявский

Локальная транскрипция подкаста через whisper.cpp

4 марта 2026 г.

Что это?  Ссылка на этот раздел

Локальный инструмент для транскрипции аудиофайлов подкаста через whisper.cpp. Устанавливается на MacOS через Homebrew и добавляется как команда subs в ~/bin.

Идея простая: в терминале набираю subs и путь к файлу, нажимаю Enter, и рядом с аудио появляются сразу три файла:

  • *.txt — чистый текст без тайм-кодов
  • *.vtt — субтитры WebVTT с тайм-кодами
  • *.srt — субтитры SRT с тайм-кодами

Это нужно не для публикации субтитров слушателям, а для себя и «машины»: поиск по транскрипциям, навигация по выпуску, дальнейшая чистка текста через ИИ и архив подкаста.

Требования  Ссылка на этот раздел

  • MacOS с Homebrew
  • FFmpeg
  • whisper.cpp (через brew)
  • Модель Whisper для whisper.cpp (в этом варианте: large-v3)

Установка  Ссылка на этот раздел

Установить FFmpeg и whisper.cpp:

BASH
1brew install ffmpeg whisper-cpp

Проверить, что ffmpeg доступен:

BASH
1ffmpeg -version

Проверить, что whisper CLI доступен (имя бинарника может отличаться, скрипт это учитывает):

BASH
1command -v whisper-cli || command -v whisper-cpp || command -v whisper

Модель: Whisper large-v3  Ссылка на этот раздел

whisper.cpp использует отдельные файлы модели. Скачиваю large-v3 один раз и храню локально.

Создать папку и скачать модель:

BASH
1mkdir -p ~/models/whisper
2cd ~/models/whisper
3curl -L -o ggml-large-v3.bin https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3.bin

Проверить, что файл на месте:

BASH
1ls -lh ~/models/whisper/ggml-large-v3.bin

Настройка: команда subs в ~/bin  Ссылка на этот раздел

Папка ~/bin  Ссылка на этот раздел

Создай папку для личных команд, если её ещё нет:

BASH
1mkdir -p ~/bin

Скрипт ~/bin/subs  Ссылка на этот раздел

Создай файл:

BASH
1nano ~/bin/subs

Вставь код:

ZSH
 1#!/usr/bin/env zsh
 2set -euo pipefail
 3
 4MODEL="${MODEL:-$HOME/models/whisper/ggml-large-v3.bin}"
 5LANG_ASR="${LANG_ASR:-ru}"
 6
 7# Находим CLI whisper.cpp
 8if command -v whisper-cli >/dev/null 2>&1; then
 9  WHISPER_BIN="whisper-cli"
10elif command -v whisper-cpp >/dev/null 2>&1; then
11  WHISPER_BIN="whisper-cpp"
12elif command -v whisper >/dev/null 2>&1; then
13  WHISPER_BIN="whisper"
14else
15  echo "Не найден whisper CLI. Установи: brew install whisper-cpp"
16  exit 1
17fi
18
19command -v ffmpeg >/dev/null 2>&1 || {
20  echo "Не найден ffmpeg. Установи: brew install ffmpeg"
21  exit 1
22}
23
24[[ -f "$MODEL" ]] || {
25  echo "Не найдена модель: $MODEL"
26  exit 1
27}
28
29cmd_name="$(basename "$0")"
30
31if [[ $# -lt 1 ]]; then
32  echo "Использование: ${cmd_name} <путь_к_файлу_или_url>"
33  exit 1
34fi
35
36INPUT="$1"
37TMPROOT="$(mktemp -d)"
38cleanup() {
39  rm -rf "$TMPROOT"
40}
41trap cleanup EXIT
42
43if [[ "$INPUT" == http://* || "$INPUT" == https://* ]]; then
44  filename="$(basename "${INPUT%%\?*}")"
45  [[ -n "$filename" ]] || filename="audio"
46  curl -L --fail "$INPUT" -o "$TMPROOT/$filename"
47  INPUT="$TMPROOT/$filename"
48  OUTDIR="$PWD"
49  OUTBASE="$OUTDIR/${filename%.*}"
50else
51  INPUT="${INPUT#file://}"
52
53  if [[ ! -f "$INPUT" ]]; then
54    echo "Не файл: $INPUT"
55    exit 1
56  fi
57
58  OUTDIR="$(cd "$(dirname "$INPUT")" && pwd)"
59  base="$(basename "$INPUT")"
60  OUTBASE="$OUTDIR/${base%.*}"
61fi
62
63# Приводим аудио к стабильному входу для whisper.cpp
64WAVTMP="$TMPROOT/input.wav"
65ffmpeg -hide_banner -loglevel error -y -i "$INPUT" -ar 16000 -ac 1 -c:a pcm_s16le "$WAVTMP"
66
67# Один запуск, сразу три формата:
68# TXT — без тайм-кодов
69# VTT — с тайм-кодами
70# SRT — с тайм-кодами
71"$WHISPER_BIN" \
72  -m "$MODEL" \
73  -f "$WAVTMP" \
74  -l "$LANG_ASR" \
75  -otxt -ovtt -osrt \
76  -of "$OUTBASE"
77
78echo "Готово:"
79echo "  ${OUTBASE}.txt"
80echo "  ${OUTBASE}.vtt"
81echo "  ${OUTBASE}.srt"

Сделай файл исполняемым:

BASH
1chmod +x ~/bin/subs

PATH: чтобы subs работала без полного пути  Ссылка на этот раздел

Если ~/bin ещё не добавлен в PATH, открой ~/.zshrc:

BASH
1nano ~/.zshrc

Добавь в конец:

BASH
1export PATH="$HOME/bin:$PATH"

Применить изменения:

BASH
1source ~/.zshrc

Проверить, что команда доступна:

BASH
1type subs

Использование  Ссылка на этот раздел

TXT, VTT и SRT рядом с файлом  Ссылка на этот раздел

BASH
1subs /путь/к/эпизоду.mp3

Результат: рядом появятся три файла:

  • эпизоду.txt
  • эпизоду.vtt
  • эпизоду.srt

Поддерживаются любые форматы, которые открывает FFmpeg: mp3, wav, m4a, flac и т.д.

URL, если нужно  Ссылка на этот раздел

Команда принимает URL, скачивает файл во временную папку и кладёт результат в текущую папку терминала:

BASH
1subs https://example.com/episode.mp3

Язык распознавания  Ссылка на этот раздел

По умолчанию используется ru. Переопределение через переменную окружения:

BASH
1LANG_ASR=en subs /путь/к/файлу.mp3

Примечания  Ссылка на этот раздел

  • txt сохраняется без тайм-кодов и подходит для чтения, поиска и дальнейшей обработки через ИИ.
  • vtt и srt почти одинаковы по содержанию, но отличаются форматом. vtt начинается со строки WEBVTT, а srt использует нумерацию блоков и запятые в тайм-кодах.
  • Тайм-коды в vtt и srt сегментные, то есть фразами, а не по словам. Для навигации по подкасту этого достаточно.
  • Используется модель large-v3. Она тяжёлая, но обычно даёт более чистую транскрипцию.
  • Скрипт всегда делает временный WAV 16 kHz mono. Это повышает стабильность обработки на длинных записях.
  • Все три файла создаются за один запуск Whisper. Это почти не увеличивает время по сравнению с генерацией одного формата.

Диагностика  Ссылка на этот раздел

  • «Не найден whisper CLI»: проверь brew install whisper-cpp и command -v whisper-cli.
  • «Не найдена модель»: проверь путь ~/models/whisper/ggml-large-v3.bin.
  • «Команда не находится»: проверь PATH в ~/.zshrc и выполни source ~/.zshrc.
  • Если распознавание идёт не на том языке, явно задай LANG_ASR=ru.
  • Если на длинной записи появляются повторы одной и той же фразы, это может быть не ошибка скрипта, а особенность самого Whisper на конкретном фрагменте аудио.

См. также  Ссылка на этот раздел

Есть что сказать? Напишите мне!
Комментировать по почте
Понравилось? Подпишитесь на меня!
RSS Телеграм