Главная → Блог → Распознавание речи на Python: от одного файла до рабочего скрипта
Распознавание речи на Python: от одного файла до рабочего скрипта
Распознавание речи на Python — это четыре строки кода. Всё остальное в этом руководстве — про неочевидное: какой формат ответа запрашивать, что делать со слишком большим файлом и почему ваш первый скрипт будет работать медленнее, чем мог бы.
Установка и первый запрос
Зависимость одна — официальный SDK OpenAI. API совместим по протоколу, отдельный клиент не нужен:
pip install openai
from openai import OpenAI
client = OpenAI(base_url="https://voicesscribe.com/v1", api_key="ваш ключ")
with open("audio.mp3", "rb") as f:
result = client.audio.transcriptions.create(model="whisper-1", file=f)
print(result.text)
Это всё. Ключ держите в переменной окружения, а не в исходниках:
import os
client = OpenAI(base_url="https://voicesscribe.com/v1", api_key=os.environ["VS_KEY"])Выбор формата ответа
По умолчанию возвращается объект с полем text. Ещё три формата имеют смысл:
| Формат | Что возвращается | Когда брать |
|---|---|---|
json | Объект с .text | По умолчанию; нужны только слова |
verbose_json | Сегменты, таймкоды, определённый язык | Таймкоды, главы, контроль качества |
srt / vtt | Готовый файл субтитров строкой | Субтитры для видео |
text | Чистая строка без обёртки | Передача в следующий инструмент |
С verbose_json в ответе есть ещё определённый язык и его вероятность — самый дешёвый сигнал качества из доступных:
r = client.audio.transcriptions.create(
model="whisper-1", file=f, response_format="verbose_json",
)
for s in r.segments:
print(f"[{s.start:6.1f}] {s.text.strip()}")
if r.language_probability < 0.6:
print("подозрительная запись — стоит проверить руками")Как правильно обрабатывать ошибки
SDK бросает типизированные исключения, поэтому обработка выходит короткой. Важно различать: часть ошибок имеет смысл повторить, часть будет падать одинаково всегда.
from openai import APIStatusError, APIConnectionError
try:
r = client.audio.transcriptions.create(model="whisper-1", file=f)
except APIConnectionError:
... # сеть — повтор оправдан
except APIStatusError as e:
if e.status_code == 401:
raise RuntimeError("неверный ключ доступа")
if e.status_code == 413:
raise RuntimeError("файл больше 25 МБ — пережать или разрезать")
if e.status_code == 429:
... # лимит или закончились минуты — подождать
raise
Ошибка 400 обычно означает пустой или битый файл. Убедитесь, что он открывается плеером, прежде чем винить API.
Файлы больше 25 МБ
Лимит запроса — 25 МБ. Два пути в порядке предпочтения.
Сначала пережать. Большинство переростков велики потому, что это wav или стерео на высоком битрейте. Моно 16 кГц — то, что модель использует внутри в любом случае:
ffmpeg -i input.wav -ac 1 -ar 16000 -b:a 48k output.mp3
После такой конвертации час звука превращается примерно в 25 МБ, и большинству файлов резка перестаёт быть нужна.
Потом резать, если всё ещё нужно. Режьте по паузам, а не по фиксированным минутам, чтобы предложения оставались целыми:
ffmpeg -i long.mp3 -f segment -segment_time 1800 -c copy part%03d.mp3Как ускорить скрипт
Первый скрипт, который пишут все, обрабатывает файлы по одному и почти всё время висит на ожидании сети. Расшифровка упирается в ввод-вывод, поэтому дело решают потоки:
from concurrent.futures import ThreadPoolExecutor
def transcribe(path):
with open(path, "rb") as f:
return client.audio.transcriptions.create(model="whisper-1", file=f).text
with ThreadPoolExecutor(max_workers=4) as pool:
texts = list(pool.map(transcribe, paths))
Значение max_workers берите из лимита запросов в секунду на вашем тарифе, а не из числа ядер процессора. Шире лимита — и успешные запросы превращаются в 429.
Точность на собственной лексике
Самый недооценённый параметр — prompt. Он не появляется в выводе, а смещает распознавание в сторону перечисленных слов:
r = client.audio.transcriptions.create(
model="whisper-1", file=f,
prompt="Продукты: Кестрел, Хокнест. Говорят: Дуарте, Иванова.",
language="ru",
)
Хорошо работают двадцать-сорок терминов, реально встречающихся в вашем аудио; абзац общего описания не даёт ничего. Добавленный language для одноязычного потока снимает ошибки определения языка на коротких записях.
Ошибки, стоящие больше всего времени
- Читать файл целиком в память, чтобы передать байтами. Передавайте файловый объект — SDK отправит его потоком.
- Повторять пустой результат. Пустая строка означает, что речи не было, а не что что-то сломалось. Повтор только тратит минуты.
- Оставлять таймаут по умолчанию на длинных файлах. Значение клиента рассчитано на короткие запросы; для часовых записей его увеличивают.
- Поднимать телефонные 8 кГц до 44 кГц в надежде на точность. Это добавляет байты, а не информацию.
Попробуйте на своих записях. Регистрация занимает минуту, бесплатных минут хватает, чтобы оценить качество.
Получить ключ бесплатноЧастые вопросы
Нужна ли специальная библиотека для Python?
Нет, официальный пакет openai работает как есть — API совместим по протоколу. От настроек OpenAI отличаются только базовый адрес и ключ.
Нужно ли готовить формат аудио средствами Python?
Специально — нет: ogg, opus, mp3, wav, m4a и webm принимаются как есть. Перевод в моно 16 кГц mp3 нужен только чтобы уложиться в лимит запроса в 25 МБ.
Как получить таймкоды в Python?
Запросите response_format=verbose_json — в ответе будут сегменты с временем начала и конца, а также определённый язык и его вероятность.
Можно ли расшифровывать несколько файлов параллельно?
Да, через ThreadPoolExecutor. Расшифровка ждёт сеть, поэтому потоки здесь правильный инструмент; размер пула ставьте ниже лимита запросов в секунду на тарифе.
Что делать с файлами больше 25 МБ?
Сначала пережать в моно 16 кГц — этого достаточно в большинстве случаев. Если файл всё ещё велик, разрежьте его по паузам и склейте результаты.
Читайте также
- Распознавание речи в Node.js: рабочий код и привычные грабли — Как расшифровывать аудио из Node.js: официальный SDK, потоки и FormData, приём загрузок в Express, таймауты и повторные попытки — с кодом, который можно вставить.
- Как построить пакетную транскрибацию архива записей — Как расшифровать тысячи записей и ничего не потерять: очередь работ, параллельность, повторные попытки, продолжение после сбоя и контроль расходов до запуска.
- Как повысить точность распознавания речи: восемь рабочих приёмов — Восемь изменений, которые действительно двигают качество расшифровки: подготовка звука, подсказка языка, параметр prompt, нарезка по паузам, форматы и замер ошибок.
- Транскрибация голосовых сообщений: Telegram, WhatsApp и другие мессенджеры — Как автоматически переводить голосовые сообщения в текст: работа с форматом ogg/opus, обработка коротких записей, примеры кода для чат-ботов.