Как озвучить целую библиотеку за один вечер при помощи ИИ

Проект «Прометей»: как озвучить целую библиотеку за один вечер при помощи ИИ

Тирекс
Тирекс Самый зубастый автор
3 марта 2026

Посмотрим, как превратить выделенный сервер в промышленную фабрику аудиокниг, способную выдавать 20 часов готового звука за 11 минут.

Изображение записи

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

В сети полно литературы, но если вы эстет и ищете что-то глубже «Онегина» или модных бестселлеров, то наверняка сталкивались с проблемой: нужной книжки в аудио просто не существует.

Так вот, тут мы попадаем в ловушку. Технологий синтеза речи (TTS) сейчас море, а вменяемого инструмента, чтобы массово превращать текст в звук, нет.

Либо вы платите корпорациям за каждый символ через официальные API, превращая чтение в дорогую привычку, либо ковыряете софт, застрявший в эпохе Windows XP, который озвучивает файлы дольше, чем вы бы читали их вслух сами.

Протокол личного ада: почему «Балаболка» больше не тянет

Каждый, кто хоть раз задавался целью превратить увесистый FB2-файл в аудио, так или иначе приходил к такой программе, как «Балаболка». Для тех, кто видит это название впервые: это бесплатная утилита для чтения текстовых файлов вслух. Она работает как посредник: вы скачиваете сторонние голосовые движки, закидываете в программу книгу, а она прогоняет текст через эти голоса и сохраняет результат в MP3 или WAV. 

Честно скажу: это великолепный софт, который годами спасал мои (и, уверен, ваши) уши. Но сегодня он упирается в системный потолок, а попытка использовать его для «промышленной» озвучки превращается в протокол личного ада. 

Главный враг — линейность. Программа спотыкается, читая текст глава за главой, страница за страницей. 

Когда вы подключаете к ней качественные нейронные голоса (например, Microsoft Neural), вы попадаете в ловушку ограничений API. Софт обращается к облаку в один-единственный поток. В итоге скорость генерации лишь немногим превышает скорость человеческой речи. Если книга рассчитана на 15 часов прослушивания, «Балаболка» будет ее обрабатывать те же 15 часов, а то и дольше. 

Наконец, есть ресурсный голод и ограничения GUI. На длинных дистанциях интерфейсные приложения Windows часто демонстрируют утечки памяти. Интерфейс начинает подтормаживать, а любой системный сбой или случайная перезагрузка обрывают многочасовую запись без возможности восстановления прогресса.

Я ощутил этот «голод» физически, когда нужно было озвучить пласт научной литературы. Пока домашний десктоп шумел вентиляторами, а прогресс двигался крайне медленно, мой сервер в дата-центре простаивал без нагрузки. 

Стало очевидно: озвучивать книгу объемом в миллион знаков через «окна» и кнопки — это в 10–15 раз медленнее, чем позволяет пропускная способность современных сетей. Мне нужно было решение, способное работать автономно и утилизировать гигабитный канал связи на 100%.

Архитектура «Прометея»

Идея «Прометея» родилась из простого админского вопроса: «Зачем ждать одного диктора, если я могу нанять 16?». Если облако Microsoft (через edge-tts) ограничивает скорость на одно соединение, значит, нам нужно много соединений. Было решено применить принцип «Divide et impera» — разделяй и властвуй. Вместо того чтобы просить нейросеть прочитать книгу целиком, мы рубим ее на куски (мелкие чанки) и запускаем армию виртуальных дикторов одновременно.

Параллелизм на стероидах (xargs -P)

Облако Microsoft (Edge TTS) ограничивает скорость отдачи потока на одно соединение, но практически не ограничивает количество одновременных запросов с одного IP. То есть использование инструмента xargs с флагом -P (parallel) позволяет запустить 12–16 потоков одновременно. 

В таком режиме мы заставляем облако работать на пике производительности, утилизируя доступный канал связи, а не ожидая своей очереди в однопоточном режиме. Это превращает процесс из изнурительного ожидания в высокоскоростную конвейерную сборку.

Проблема «битого символа» и fold -s

Первые тесты параллельной сборки выявили проблему. Кириллица в UTF-8 не так проста: каждый символ занимает два байта. Если резать файл как есть, по размеру (байтам), разрез обязательно попадает на середину буквы. В итоге вместо текста Python получает «мусорный» байт, вылетает с ошибкой «UnicodeDecodeError», и процесс сразу крашится.

Решение нашлось в классической утилите fold с флагом -s. Она умеет делать «мягкие» переносы строк, ориентируясь на пробелы. Это гарантирует, что каждый чанк текста останется валидным для Python-декодера, а слова не будут превращены в нечитаемый набор байтов. Теперь данные уходят в облако в идеальном состоянии.

Инфраструктурный минимализм

Предрекаю ваш вопрос: «Почему не через виртуальное окружение Python?». Мой подход строится на принципе «одна задача — один сервер». Разворачивая «Прометей» на выделенном воркере, я превращаю его в узкоспециализированный вычислительный модуль. 

Изоляция через venv здесь избыточна. Она лишь усложняет цепочку вызовов в Bash-скриптах и добавляет лишний слой абстракции там, где нужна прямая работа с системными бинарниками. Нам нужен максимально короткий путь от текста к звуку. 

Disk-First против RAM-First

Многие админы по привычке используют /tmp (tmpfs) для хранения временных данных. Однако при озвучке тяжелых книг на 170+ чанков объем промежуточных MP3-данных легко переваливает за 2 ГБ. На бюджетных инстансах это приведет к ошибке «No space left on device».

Чтобы не зависеть от объемов RAM, весь рабочий цикл «Прометея» перенесен на физический диск (NVMe). Это гарантирует стабильность на любых объемах: будь то короткая статья или многотомный архив научной литературы.

Бенчмарки и стресс-тест 

Для испытаний был выбран выделенный сервер Selectel конфигурации CL13. Под капотом у него:

  • CPU: 12th Gen Intel Core i3-12100 (4 ядра / 8 потоков);
  • RAM: 16 ГБ DDR4;
  • Disk: Samsung 970 EVO Plus 500 ГБ (NVMe);
  • OS: Debian 12 Stable.

Именно его NVMe-шина должна была выдержать шквал одновременных записей. В качестве подопытного объекта я взял книгу Адама Хиггинботама «Чернобыль. История катастрофы». Почему именно ее? Это сложный текст с обилием технических терминов, фамилий и цифр — идеальный стресс-тест для интонаций нейронки.

В 13:50 мы запустили конвейер в 12 потоков. Книга объемом около 1,2 млн знаков была разбита на 172 чанка. К 13:57 система вышла на пик сетевой активности, показывая 91% готовности, а еще через минуту генерация всех чанков была завершена. Спустя еще три минуты, в 14:01, ffmpeg в режиме copy mode склеил их в один файл.

В итоге на 24 часа готового аудио ушло всего 11 минут. За это время я мог заварить себе чай, пока система выдает результат с коэффициентом ускорения x130. После этого возвращаться к «Балаболке», где тот же процесс растянулся бы на сутки ожидания, кажется просто бессмысленным.

Анализ системных метрик

Пока на экране мелькали проценты прогресса, мне было интересно заглянуть в систему изнутри и узнать, как сервер Selectel переваривает этот массив из 12 потоков озвучки.

Первым делом я проверил дисковую активность через iostat. При суммарной скорости записи около 21 МБ/с утилизация NVMe-накопителя составила всего 1,6%. Задержка записи (w_await) в 2,4 мс подтверждает: для современного диска такая нагрузка — это даже не разминка, он ее просто не замечает.

Нагрузка на диск (iostat):

Device       w/s      wkB/s    w_await  %util

nvme0n1      203.00   21540.00  2.44     1.60

Процессор i3-12100 (Alder Lake) вполне неплохо и стабильно управляет 12 потоками. Текущая вычислительная мощность используется не полностью, так что тут есть небольшой запас на разбег в случае необходимости — сохраняется запас производительности и низкое время отклика.

Нагрузка на CPU (top):

load average: 0.23, 0.08, 0.02

%Cpu(s):  2.3 us,  2.3 sy,  0.0 ni, 95.5 id

Вопросы «аудиофилов» 

Слышу вопрос от эстетов: «А как же связность речи на стыках чанков?» Технически каждая нейронная сессия в edge-tts — это независимый акт генерации. Однако благодаря тому, что мы используем fold -s, разрез файла происходит строго на границах слов и предложений.

Нейросетевой движок Microsoft Neural достаточно умен: он имеет встроенные алгоритмы «вдоха» и «выдоха» в начале и конце каждой фразы. В итоге стыки чанков воспринимаются слушателем как естественные паузы диктора между абзацами. На скорости 1,2x с включенной функцией «Skip Silence» в плеере переходы становятся абсолютно бесшовными.

Инструкция по развертыванию

Я делюсь этой технологией по принципу «не жалко». Ресурс должен приносить пользу, а не гнить в приватных папках. Ниже — ваш пошаговый маршрут к созданию собственной системы генерации контента (или фабрики аудиокниг, кому как больше нравится) и детальный разбор того, как это работает изнутри.

Подготовка среды

Сначала необходимо зайти на сервер под пользователем `root`. Мы развернем базовый набор инструментов: Python для работы движка, FFmpeg для обработки звука, Pandoc для парсинга книг из FB2 и Aria2 для скоростной закачки моделей и данных.

Весь процесс подготовки занимает меньше минуты. Последовательно выполните следующие команды.

Установка системных пакетов и движка


      apt update && apt install -y python3-pip ffmpeg pandoc aria2

pip install edge-tts --break-system-packages

Флаг –break-system-packages необходим в современных версиях Debian/Ubuntu для установки Python-пакетов глобально, минуя виртуальные окружения.

Создание структуры директорий

Чтобы файлы не перемешивались, создадим рабочую иерархию папок для текстов, готового аудио и временных файлов:


      mkdir -p /root/books/{text,audio,tmp}

Скрипт prometheus.sh (v7.2.1 Master Edition)

Теперь создадим управляющий скрипт. Вам нужно создать файл в папке /root/, вставить в него код и разрешить системе его запуск (дать право на запуск) командой chmod +x. Для этого:

  1. создайте файл: nano /root/prometheus.sh;
  2. вставьте код скрипта;
  3. сохраните (Ctrl+O, Enter) и выйдите (Ctrl+X);
  4. сделайте файл исполняемым (код ниже).

      chmod +x /root/prometheus.sh
Показать код скрипта (кликните, чтобы развернуть).
#!/bin/bash

# ======================================================

# PROJECT PROMETHEUS v7.2.1 | MASTER EDITION

# ======================================================

# КОНФИГУРАЦИЯ

THREADS=12                # Оптимально для стабильности без бана по IP

VOICE="ru-RU-DmitryNeural" # Эталонный мужской голос

RATE="+15%"               # Сжатие пауз и темп

OUTPUT_BASE="/root/books/audio"

TEMP_BASE="/root/books/tmp"

# 1. ВВОД ДАННЫХ (Поддерживает автозаполнение через Tab)

read -e -p "Путь к файлу (txt/fb2): " INPUT_PATH

INPUT_PATH=$(echo "$INPUT_PATH" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//")

[ ! -f "$INPUT_PATH" ] && echo "ERR: Файл не найден!" && exit 1

# 2. ПОДГОТОВКА

WORKDIR="${TEMP_BASE}/work_$(date +%s)"

mkdir -p "$WORKDIR" "$OUTPUT_BASE"

# 3. ПАРСИНГ МЕТАДАННЫХ (Вытаскиваем автора и название из FB2)

FILE_EXT="${INPUT_PATH##*.}"

ORIG_NAME=$(basename "$INPUT_PATH" ."$FILE_EXT")

if [[ "$FILE_EXT" == "fb2" ]]; then

    F_NAME=$(grep -i -oP '(?<=<first-name>).*?(?=</first-name>)' "$INPUT_PATH" | head -1)

    L_NAME=$(grep -i -oP '(?<=<last-name>).*?(?=</last-name>)' "$INPUT_PATH" | head -1)

    TITLE=$(grep -i -oP '(?<=<book-title>).*?(?=</book-title>)' "$INPUT_PATH" | head -1)

    BOOK_NAME="${L_NAME}_${F_NAME}__${TITLE}"

    # Fallback если метаданные кривые

    [ ${#BOOK_NAME} -lt 10 ] && BOOK_NAME="$ORIG_NAME"

    pandoc -f fb2 -t plain "$INPUT_PATH" -o "$WORKDIR/raw.txt"

else

    BOOK_NAME="$ORIG_NAME"

    cp "$INPUT_PATH" "$WORKDIR/raw.txt"

fi

# Санитизация имени файла (убираем мусорные символы)

BOOK_NAME=$(echo "$BOOK_NAME" | sed 's/[[:space:]]/_/g' | sed 's/[\\/:"*?<>|]//g')

FINAL_FILE="$OUTPUT_BASE/${BOOK_NAME}.mp3"

echo -e ">>> ЗАПУСК ПРОТОКОЛА: ${BOOK_NAME}.mp3"

# 4. ОБРАБОТКА ТЕКСТА И НАРЕЗКА

sed '/^$/d' "$WORKDIR/raw.txt" > "$WORKDIR/source.txt"

fold -s -w 2000 "$WORKDIR/source.txt" | tr -d '\r' > "$WORKDIR/formatted.txt"

split -l 100 -d -a 4 "$WORKDIR/formatted.txt" "$WORKDIR/part_"

TOTAL_PARTS=$(ls "$WORKDIR"/part_[0-9]* | wc -l)

# 5. КОНВЕЙЕРНАЯ ОЗВУЧКА

export VOICE WORKDIR RATE

do_tts() {

    local file=$1

    edge-tts --rate="$RATE" --voice "$VOICE" --file "$file" --write-media "$file.mp3" > /dev/null 2>&1

}

export -f do_tts

# Очередь через xargs (вот здесь живет скорость)

ls "$WORKDIR"/part_[0-9]* | xargs -P $THREADS -I {} bash -c 'do_tts "{}"'

# 6. СКЛЕЙКА (БЕЗ ПОТЕРИ КАЧЕСТВА)

ls "$WORKDIR"//6ef4e6a1-9d49-47ac-bfed-170f67a815cf.selcdn.net/part_*.mp3 | sort | xargs -I {} echo "file '{}'" > "$WORKDIR/list.txt"

ffmpeg -f concat -safe 0 -i "$WORKDIR/list.txt" -c copy -y "$FINAL_FILE" > /dev/null 2>&1

rm -rf "$WORKDIR"

echo "ГОТОВО! Файл: $FINAL_FILE"

Заключение

«Прометей» — это манифест эффективности. Пока корпорации строят заборы вокруг своих API, мы строим мосты из Bash-скриптов. Я озвучил более 40 часов эксклюзивного контента за один вечер просто потому, что могу. Теперь это можете сделать и вы.

Не ждите, пока за вас решат, что и как вам слушать. Делайте это сами.