API-ключ TTS в Python: настройка, потоковая передача, JSON-режим, JSON-режим
Это руководство по Python для API этого сайта: сохраните ключ, создайте клиент, используйте потоковую передачу, принудительно включите вывод JSON и обработайте лимиты запросов. Сначала важное замечание: API генерирует текст, а не аудио.
Обновлено

Ключевые моменты
- Эндпоинт совместим с OpenAI, поэтому пакет openai для Python работает с base_url, установленным в https://api.ttsapihub.com/v1.
- Храните ключ в переменной окружения, никогда не храните его в исходном коде.
- Поддерживаются потоковая передача, JSON-режим и вызов функций; вывод аудио не поддерживается.
- Обрабатывайте HTTP 429 с короткой задержкой и читайте X-Balance-USD для отслеживания расходов.
Проверьте, что открывает ключ
Люди, которые ищут пример API-ключа TTS для Python, обычно хотят преобразовать текст в озвученное аудио. Ключ от этого сервиса этого не делает. Он аутентифицирует запросы к текстовой LLM: POST /v1/chat/completions и GET /v1/models, используя модель uncensored. Здесь нет синтеза речи, загрузки аудио и эмбеддингов.
Если это подходит для вашего проекта, например, потому что вы генерируете сценарии, диалоги или озвучку, которые передаёте отдельному инструменту синтеза речи, остальная часть этой страницы даёт вам рабочий код Python. Если вам нужен вывод аудио непосредственно от API, это не тот сервис, и лучше узнать об этом сейчас. Документация перечисляет точный набор функций.
Практичный способ использовать генерацию текста в аудио-проекте — рассматривать её как этап написания сценария. Модель составляет черновик озвучки, переписывает реплику под ограничение по времени или превращает заметки в диалог с несколькими говорящими. Ваш Python-код затем передаёт итоговый текст тому инструменту синтеза речи, который вы используете. Разделение этапов также позволяет менять любой из них, не затрагивая другой, и вы платите этому API только за написанные им слова.
Для работы вам нужны Python 3.9 или новее и API-ключ. Зарегистрируйтесь на странице API-ключ и получите пробный баланс в один клик на $0,50; он действует 7 дней и не требует привязки карты.
Сохраните ключ и установите пакет
Никогда не записывайте API-ключ в файл, который вы закоммитите. Поместите его в переменную окружения и считывайте во время выполнения.
# base URL used below: https://api.ttsapihub.com/v1 , model: uncensored
pip install openai
export API_KEY="paste-your-key-here"В PowerShell для Windows эквивалентом является $env:API_KEY = "paste-your-key-here". Для проекта файл .env, загружаемый пакетом, таким как python-dotenv, является распространённым шаблоном, пока .env находится в вашем .gitignore.
Если ключ попадёт в репозиторий, считайте его сгоревшим: удалите его из истории, если можете, и запросите новый. Помните, что ключи тратят предоплаченный баланс, поэтому утечка ключа — это также финансовая утечка.
Создайте клиент и выполните первый запрос
Официальный пакет принимает base_url. Всё остальное — обычная форма вызова OpenAI.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ttsapihub.com/v1",
api_key=os.environ["API_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You write short narration scripts."},
{"role": "user", "content": "Draft a 40-word intro for a podcast about night trains."},
],
temperature=0.8,
max_tokens=200,
)
print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)Объект usage показывает, сколько токенов использовал запрос, чтобы вы могли вычислить стоимость: токены ввода умножить на $0,15 за миллион, плюс токены вывода умножить на $0,50 за миллион. Если запрос выше использовал 60 токенов ввода и 80 токенов вывода, стоимость составляет $0,000009 плюс $0,00004, что равно $0,000049. Неудачные или отклонённые запросы не оплачиваются.
max_tokens — необязательный параметр. Без него завершение может использовать всё, что осталось от контекстного окна в 100 000 токенов, поэтому устанавливайте его, когда хотите жёсткий лимит длины и стоимости.
Потоковая передача ответа
Потоковая передача возвращает токены по мере их генерации с использованием событий, отправляемых сервером. Установите stream=True и итерируйте.
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Describe a rainy station platform in four sentences."}],
stream=True,
)
parts = []
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta.content or ""
parts.append(delta)
print(delta, end="", flush=True)
text = "".join(parts)Проверка на пустой список choices нужна, потому что последнее событие потока может содержать данные об использовании и не содержать текста. Пропуск этого события позволяет избежать ошибки индекса. Один операционный момент: потоковый запрос удерживает слот параллельных запросов до конца потока. Если вы запустите много стримов в потоках выполнения и никогда не дочитаете их до конца, вы упрётесь в лимит параллельных запросов, даже если ваша частота запросов низкая.
Запросите JSON и вызовите инструменты
JSON-режим
Установите response_format в объект JSON, чтобы сделать ответ пригодным для разбора. Также сообщите модели в промпте, что вы хотите JSON; настройка ограничивает формат, а промпт указывает форму.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply only with JSON: {\"title\": str, \"beats\": [str]}"},
{"role": "user", "content": "Outline a three-beat radio drama about a lost key."},
],
)
data = json.loads(resp.choices[0].message.content)
print(data["title"], len(data["beats"]))Всё равно оберните json.loads в блок try. Ответ, достигший max_tokens, может быть обрезан посередине объекта.
Вызов функций
Передайте tools и опционально tool_choice. Когда модель запрашивает инструмент, выполните его самостоятельно и отправьте результат обратно как сообщение с role: "tool".
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
tools = [{
"type": "function",
"function": {
"name": "word_count",
"description": "Count the words in a text",
"parameters": {
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
},
}]
messages = [{"role": "user", "content": "How many words are in: the quick brown fox?"}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
msg = first.choices[0].message
if msg.tool_calls:
call = msg.tool_calls[0]
args = json.loads(call.function.arguments)
result = len(args["text"].split())
messages.append(msg)
messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)Ведите разговор и следите за бюджетом токенов
API не имеет состояния. Если вы хотите чат, который помнит, что было сказано, вы храните список сообщений в своей программе и отправляете его полностью с каждым запросом. Небольшой класс решает эту задачу, и это также правильное место для ограничения истории, чтобы стоимость не росла.
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
history = [{"role": "system", "content": "You are a dialogue writer. Keep replies under 120 words."}]
def say(user_text, keep_last=12):
history.append({"role": "user", "content": user_text})
# keep the system message plus the most recent turns
trimmed = [history[0]] + history[1:][-keep_last:]
resp = client.chat.completions.create(model="uncensored", messages=trimmed, max_tokens=250)
reply = resp.choices[0].message.content
history.append({"role": "assistant", "content": reply})
return reply, resp.usage.total_tokens
print(say("Open a scene in a ticket office at closing time.")[0])Обрезка истории важна для экономии больше, чем для контекстного окна. Модель принимает до 100 000 токенов в сумме, но если каждый ход заново отправляет 30 000 токенов истории, каждый запрос стоит $0,0045 только за ввод (30 000 × $0,15 за миллион). Пятьдесят таких ходов дадут $0,225 ещё до учёта хотя бы одного выходного токена. Сохранение последних двенадцати ходов или краткое изложение старых в короткую заметку обычно сохраняет качество и резко снижает счёт.
Параллельность — второй момент, который нужно учесть при проектировании. Если ваша программа обслуживает несколько пользователей одновременно, семафор с размером, равным лимиту вашего ключа (8 для полного ключа, 2 для пробного), убережёт вас от ошибки concurrency. Запросы выше лимита ждут в вашей собственной очереди, а не завершаются ошибкой, что удобнее, чем повторные попытки после 429.
Тестирование тоже стоит упоминания. Напишите небольшой скрипт, который вызывает API с фиксированным seed, низкой температурой и коротким max_tokens, и запускайте его при изменении промптов или настроек. Сид и низкая температура делают вывод более повторяемым, что позволяет сравнивать две версии промптов без шума. Держите эти проверки крошечными; тест, который стоит долю цента, может запускаться при каждом коммите, не привлекая внимания к счёту.
Наконец, логируйте ID запроса из каждого ответа. Когда запрос ведёт себя странно, этот ID — самый быстрый способ указать поддержке на точный запрос.
Обработка лимитов, ошибок и баланса
Полный ключ позволяет 8 параллельных запросов и 300 запросов в минуту. Пробный ключ позволяет 2 и 60. Превышение первого возвращает HTTP 429 с кодом ошибки concurrency, а превышение второго возвращает 429 с rate_limited. Временная перегрузка также возвращает 429 с заголовком Retry-After: 5.
Пакет OpenAI автоматически повторяет попытки при некоторых сбоях, и вы можете увеличить это значение с помощью max_retries. Для пакетной задачи добавьте также собственное ограничение на параллельную работу, чтобы оставаться в пределах лимита параллельных запросов, а не полагаться на повторные попытки.
import os
from openai import OpenAI, RateLimitError
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"], max_retries=3)
raw = client.chat.completions.with_raw_response.create(
model="uncensored",
messages=[{"role": "user", "content": "One sentence about trains."}],
max_tokens=60,
)
print("balance:", raw.headers.get("X-Balance-USD"))
print("request id:", raw.headers.get("X-Request-Id"))
print(raw.parse().choices[0].message.content)Заголовки ответа X-Request-Id и X-Balance-USD полезны в логах. Цитируйте ID запроса при обращении в поддержку. Стоимость указана на странице цен: $0,15 за 1M входных токенов и $0,50 за 1M выходных токенов, с пополнениями от $20 до $500 и бонусами 5%, 10% и 15% при $50, $100 и $200. Принимаются карты (Visa, Mastercard, Apple Pay, Google Pay) и криптовалюта (USDT на TRC20, USDC на Base). Промпты не используются для обучения. Модель предназначена для законного использования взрослыми, а сексуальный контент с участием несовершеннолетних никогда не разрешён.
Дополнительные руководства
Вопросы и ответы
Работает ли этот API-ключ для синтеза речи в Python?
Нет. Ключ аутентифицирует текстовый LLM API без вывода аудио. Используйте его для генерации текста, затем передайте этот текст инструменту синтеза речи.
Какой пакет Python выбрать?
Официальный пакет openai. Установите base_url в https://api.ttsapihub.com/v1 и модель в uncensored.
Как не хранить ключ в коде?
Читайте его из переменной окружения, например API_KEY, и исключите любой файл .env из системы контроля версий.
Как узнать стоимость запроса?
Читайте resp.usage для подсчёта токенов и заголовок ответа X-Balance-USD для оставшегося баланса.
Что происходит при достижении лимита запросов?
API возвращает HTTP 429 с кодом rate_limited или concurrency. Подождите несколько секунд и повторите запрос; неудачный запрос не оплачивается.
До вашего ключа — всего одна форма
Создайте аккаунт, скопируйте ключ, измените базовый URL. Это вся настройка.