Хочешь слушать книги, которых нет в озвучке, — в мужском голосе, с паузами между главами, на своём iPhone или в Apple Books?
Рассказываю, как я превратил электронную книгу EPUB в .m4b аудиофайл с высоким качеством синтеза речи.
📘 Что мы будем делать
- Возьмём файл в формате .epub
- Озвучим его голосом Дмитрия (Azure TTS) — реалистичный мужской голос
- Добавим метаданные: название, автора
- Сохраним в формате .m4b, который поддерживают iPhone и BookPlayer
- Получим файл, идеально подходящий для офлайн-прослушивания на телефоне
✅ Что понадобится
- Сервер или компьютер с Linux (подойдёт Ubuntu 20+)
- Python 3.10+
- Аккаунт в Microsoft Azure
- Базовые знания командной строки
🔐 Регистрация и получение Azure Speech API ключа
- Зарегистрируйся на https://portal.azure.com
- Создай ресурс типа “Speech”:
- Группа ресурсов: любая
- Регион: East US или East US 2
- Тариф: Free F0 (включает до 5 часов озвучки в месяц)
Перейди в созданный ресурс → вкладка “Ключи и конечная точка”
Скопируй:
- Key 1 — это будет твой API ключ
- Endpoint — например: https://eastus2.api.cognitive.microsoft.com/
❗ Не публикуй свой ключ публично — это доступ к твоим лимитам.
⚙️ Установка зависимостей и создание окружения
создаем директорию
mkdir -p ~/epub_to_m4b
cd ~/epub_to_m4b
# затем загрузка файла EPUB через Termius → Local Files → Upload
ставим системные зависимости
sudo apt update
sudo apt install ffmpeg python3-venv -y
создаем и активируем окружение
python3 -m venv venv
source venv/bin/activate
Ставим зависимости python в окружении
pip install ebooklib beautifulsoup4 requests pydub mutagen
📜 Создаем скрипт: epub_to_m4b_with_meta.py
nano epub_to_m4b_with_meta.py
Вставь содержимое ниже, замени ключ и регион на свои:
import os
import time
import glob
import requests
from ebooklib import epub
from ebooklib import ITEM_DOCUMENT
from bs4 import BeautifulSoup
from pydub import AudioSegment
from mutagen.mp4 import MP4
# ✅ Azure Speech настройки
AZURE_KEY = 'ВСТАВЬ_СЮДА_СВОЙ_API_КЛЮЧ'
AZURE_REGION = 'eastus2'
VOICE = 'ru-RU-DmitryNeural'
HEADERS = {
'Ocp-Apim-Subscription-Key': AZURE_KEY,
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': 'audio-16khz-32kbitrate-mono-mp3'
}
# 🔍 Поиск первого EPUB в текущей директории
def find_epub_file():
epub_files = glob.glob("*.epub")
if not epub_files:
raise FileNotFoundError("❌ EPUB-файл не найден в текущей директории.")
return epub_files[0]
# 📖 Чтение названия и автора (с защитой)
def get_metadata(epub_path):
try:
book = epub.read_epub(epub_path)
except KeyError as e:
raise Exception(f"❌ EPUB повреждён: отсутствует файл {e}") from None
title = book.get_metadata('DC', 'title')
creator = book.get_metadata('DC', 'creator')
return (
title[0][0] if title else "EPUB AudioBook",
creator[0][0] if creator else "Unknown Author"
)
# 📚 Извлечение глав с текстом
def extract_chapters(epub_path):
try:
book = epub.read_epub(epub_path)
except KeyError as e:
raise Exception(f"❌ Ошибка чтения EPUB: {e}") from None
chapters = []
for item in book.get_items():
if item.get_type() == ITEM_DOCUMENT:
soup = BeautifulSoup(item.content, 'html.parser')
text = soup.get_text(separator=' ', strip=True)
if len(text.strip()) > 200:
title = item.get_name().split('/')[-1]
chapters.append((title, text))
return chapters
# 🗣️ Синтез одной главы
def synthesize(text, filename):
ssml = f"""<speak version='1.0' xml:lang='ru-RU'>
<voice xml:lang='ru-RU' xml:gender='Male' name='{VOICE}'>{text}</voice></speak>"""
url = f"https://{AZURE_REGION}.tts.speech.microsoft.com/cognitiveservices/v1"
response = requests.post(url, headers=HEADERS, data=ssml.encode('utf-8'))
if response.status_code == 200:
with open(filename, 'wb') as f:
f.write(response.content)
else:
raise Exception(f"TTS failed: {response.status_code} {response.text}")
# 🎧 Объединение mp3 в .m4b и добавление метаданных
def build_m4b(chapters_folder, output_file, title, author):
if os.path.exists(output_file):
os.remove(output_file)
chapters = sorted(os.listdir(chapters_folder))
full_audio = AudioSegment.empty()
for ch in chapters:
path = os.path.join(chapters_folder, ch)
audio = AudioSegment.from_mp3(path)
full_audio += audio
full_audio.export(output_file, format='mp4')
audio_file = MP4(output_file)
audio_file["\xa9nam"] = title
audio_file["\xa9ART"] = author
audio_file["\xa9alb"] = title
audio_file["trkn"] = [(1, 1)]
audio_file.save()
# 🚀 Точка входа
if __name__ == "__main__":
EPUB_FILENAME = find_epub_file()
print(f"📘 Найден файл: {EPUB_FILENAME}")
title, author = get_metadata(EPUB_FILENAME)
print(f"📖 Название: {title}")
print(f"✍️ Автор: {author}")
# Безопасное имя файла
safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '-', '_')).strip().replace(" ", "_")
output_file = f"{safe_title}.m4b"
os.makedirs("audio", exist_ok=True)
chapters = extract_chapters(EPUB_FILENAME)
for idx, (chapter_title, text) in enumerate(chapters):
print(f"▶️ Синтез главы {idx + 1}/{len(chapters)}: {chapter_title}")
filename = f"audio/chapter_{idx+1:03}.mp3"
if not os.path.exists(filename):
synthesize(text[:5000], filename)
time.sleep(0.5)
build_m4b("audio", output_file, title, author)
print(f"✅ Готово: {output_file}")
- Сохрани: Ctrl+O, Enter, Ctrl+X
- Активируй среду (если нужно):
source venv/bin/activate
- Запусти:
python epub_to_m4b_with_meta.py
🧪 Пример вывода
📲 Как слушать на iPhone
- Скопируй .m4b на iPhone через Termius или AirDrop
- Открой в приложении BookPlayer, Voice Dream или Apple Books
- Наслаждайся качественной мужской озвучкой своей книги 🎧