Перейти к содержимому
EN

Музыка

Музыка работает по той же асинхронной схеме, что и видео: задача, опрос, скачивание.

import requests
job = requests.post(
"https://api.mixen.ai/v1/audio/music",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"model": "suno", "prompt": "Меланхоличный синти-поп о ночном городе, женский вокал"},
).json()
print(job["id"], job["status"])
Поле Описание
model suno / suno-v6 — песня с вокалом, два трека за запрос. lyria / lyria-pro — инструментал, один трек
mode simple (по prompt) или custom (по lyrics + style + title). Lyria режим игнорирует
prompt Описание трека для простого режима. Потолок зависит от модели: Suno — 3 000 символов в simple и 5 000 в custom (lyrics, поле ниже); Lyria жёсткого лимита не имеет
lyrics Текст песни для авторского режима
style Жанр, стиль, теги
title Название трека

Когда нужен конкретный текст, а не сгенерированный:

{
"model": "suno-v6",
"mode": "custom",
"title": "Ночной трамвай",
"style": "indie rock, 90s, мужской вокал, живые барабаны",
"lyrics": "Первый куплет...\n\nПрипев..."
}
curl https://api.mixen.ai/v1/audio/music/music_... \
-H "Authorization: Bearer $MIXEN_API_KEY"
curl -L https://api.mixen.ai/v1/audio/music/music_.../content \
-H "Authorization: Bearer $MIXEN_API_KEY" -o track.mp3

Статусы те же: queued → in_progress → completed либо failed.

Suno возвращает два варианта трека за один запрос — это особенность модели, а не ошибка. Оба доступны в ответе на опрос статуса, конкретный трек скачивается параметром ?index=N эндпоинта /audio/music/{id}/content (нумерация с нуля, по умолчанию 0).

Задача, не завершившаяся за 15 минут, помечается failed при следующем опросе и не оплачивается.

Без опроса: webhook, ожидание, идемпотентность

Заголовок раздела «Без опроса: webhook, ожидание, идемпотентность»

Три необязательных поля тела POST /v1/audio/music — общие для видео и музыки:

Поле Что делает
webhook_url Публичный https-адрес. По статусу completed или failed мы шлём туда POST с тем же объектом задачи, что отдаёт GET. Приватные адреса и http:// отклоняются 400 invalid_webhook_url ещё до создания задачи
wait true — запрос держится, пока задача не завершится, и возвращает финальный объект (ждём до wait_timeout, по умолчанию 60 с, максимум 300). По таймауту — объект как есть (in_progress), без ошибки
idempotency_key До 128 символов. Повтор запроса с тем же ключом возвращает уже созданную задачу, а не новую (и не списывает второй раз); в ответе заголовок X-Mixen-Idempotent-Replay: true. Ключ уникален в пределах вашего аккаунта

Заголовки webhook-запроса:

Заголовок Значение
X-Mixen-Event music.completed или music.failed
X-Mixen-Delivery id задачи
X-Mixen-Signature t=<unix>,v1=<hex> — HMAC-SHA256 от строки "<t>.<сырое тело>"; секрет — sha256-hex вашего API-ключа (сам ключ мы не храним, его хэш вы считаете локально)

Ваш эндпоинт должен ответить 2xx; иначе доставка повторится через 5, 20, 60 и 180 секунд. Гарантия — «хотя бы один раз»: обрабатывайте повторы по X-Mixen-Delivery идемпотентно. Проверка подписи:

import hashlib, hmac
def verify(raw_body: bytes, header: str, api_key: str) -> bool:
secret = hashlib.sha256(api_key.encode()).hexdigest()
parts = dict(kv.split('=', 1) for kv in header.split(','))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get('v1', ''))

Музыка тарифицируется за запрос, а не за секунду: поле per_request_rub в каталоге. Два трека Suno — одна оплата.

POST /v1/audio/music/price принимает то же тело, что и POST /v1/audio/music, и возвращает сумму, не запуская генерацию и ничего не списывая. Считается той же формулой, что и фактическое списание, поэтому котировка совпадает с чеком; валидация тоже общая — невалидные параметры дадут те же 400/404, что и запуск.

{
"object": "price",
"model": "suno",
"model_id": "suno-music-generate",
"price": {"rub": 8.0047, "usd": 0.09},
"per_unit": {"rub": 8.0047, "unit": "generation"},
"quantity": 1,
"params": {"mode": "simple", "tracks": 2}
}

Рублёвая сумма считается по живому курсу — берите котировку непосредственно перед запуском, а не кешируйте.