API загрузки и кавера в один шаг
Описание эндпоинта
Загрузка и кавер в один шаг отправляет аудиофайл или URL аудио и создаёт на основе этого исходного аудио новую версию кавера.
Эндпоинт: POST /api/music/upload-cover
Оплата: платно, сейчас по умолчанию 0,6 ¥ за вызов. Этот эндпоинт — «загрузить и сделать кавер», речь не о загрузке картинки-обложки. Фактически списанная сумма следует текущей конфигурации цен в бэк-офисе.
Max Mode / Variety: эндпоинт поддерживает необязательные параметры max_mode и variety (0-4). При включённом
max_mode этот вызов тарифицируется по двойной цене (0,6 → 1,2 ¥ за вызов); variety не стоит
ничего дополнительно. Что они означают и как их отправлять — в разделе «Расширенные параметры»
Обзора нового API.
Время ожидания и тайм-ауты (важно): это синхронный эндпоинт — заказ принимается и передаётся в генерацию только при получении ответа. По измерениям большинство запросов отвечают за 1-3 секунды, около 10% занимают больше 30 секунд, а самый долгий — около 230 секунд. Установите тайм-аут клиента 300 секунд или больше; отсутствие ответа не означает, что ничего не сгенерировано, и не повторяйте запрос сразу после тайм-аута (это дублирует заказ и списывает деньги повторно). Если соединение оборвалось, проверьте позже через
GET /api/music/songs. См. «Время ожидания и настройка тайм-аута» в Обзоре нового API.
При большом аудио «загрузку» и «кавер» лучше разнести на два шага (рекомендуется)
Этот эндпоинт требует поместить всё аудио в тело запроса: чем больше аудио, тем больше тело, и одна сетевая заминка или тайм-аут обрывают передачу на полпути, после чего сервер возвращает
unexpected end of JSON input(HTTP 400, без списания).Если аудио больше примерно 8 МБ, сеть нестабильна или один и тот же исходный материал будет использоваться несколько раз, переходите на двухшаговую форму:
POST /api/music/upload-sourceсначала загружает исходное аудио — бесплатно, можно повторять в любой момент — и отдаётclip_id;POST /api/music/generate-from-sourceзапускает кавер с этимclip_id— тело платного шага всего около 250 байт.См. API загрузки исходного аудио, API кавера по исходному клипу и «Большие файлы и обрезанные запросы» в конце этой страницы.
Параметры запроса
Headers
| Параметр | Тип | Обязательно | Примечания |
|---|---|---|---|
| Authorization | string | да | Bearer YOUR_API_KEY |
| Content-Type | string | да | application/json |
Параметры тела
| Параметр | Тип | Обязательно | По умолчанию | Примечания |
|---|---|---|---|---|
| model | string | нет | suno-v6 | Название модели для клиента: suno-v6, suno-v6-wild или suno-v6-mini |
| file_url | string | нет | - | URL исходного аудио |
| file_base64 | string | нет | - | Аудио в Base64 |
| file_name | string | нет | - | Имя файла |
| prompt | string | нет | - | Новый текст или направление адаптации |
| style | string | нет | - | Теги стиля |
| title | string | нет | - | Название |
| negativeTags | string | нет | - | Негативный стиль |
| instrumental | boolean | нет | false | Инструментальная ли композиция |
| waitAudio | boolean | нет | false | Ждать ли завершения аудио |
| cover_start_s | number | нет | - | Секунда начала переделываемого фрагмента |
| cover_end_s | number | нет | - | Секунда конца переделываемого фрагмента |
| audio_weight | number | нет | - | Зависимость от референсного аудио, диапазон 0.0-1.0; можно передавать только при указании референсного аудио |
cover_start_s и cover_end_s задаются в секундах и могут быть дробными; время начала должно быть меньше времени конца и не превышать длительность исходного аудио. Если оба поля опущены, используется всё аудио. audio_weight отображается на metadata.control_sliders.audio_weight в Suno и управляет тем, насколько результат опирается на референсное аудио; принимает 0.0-1.0 и может передаваться только когда в запросе есть действующее референсное аудио в file_url или file_base64. 0 — допустимое значение; пропуск поля означает «не указано» и сохраняет поведение Suno по умолчанию. instrumental и waitAudio должны быть логическими значениями JSON, не строками.
Эндпоинт загрузки по умолчанию отвечает асинхронно. Пока clips[].status в ответе равен pending, пустой audio_url — это нормально и не означает, что загрузка или кавер не удались; сохраните полученный реальный song_id и опрашивайте эндпоинт запроса песен до завершения, прежде чем читать адрес аудио.
Пример запроса
curl -X POST https://www.suno-api.io/api/music/upload-cover \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"file_url": "https://example.com/source.mp3",
"file_name": "source.mp3",
"prompt": "Новый текст или направление адаптации",
"style": "Mandopop, acoustic guitar",
"title": "Версия кавера",
"negativeTags": "noise, low quality",
"audio_weight": 0.5,
"instrumental": false,
"waitAudio": false,
"cover_start_s": 0,
"cover_end_s": 60
}'
Ответ
{
"code": 200,
"message": "success",
"data": {
"upload": {
"clip_id": "uploaded_clip_id",
"status": "complete"
},
"clips": [
{
"song_id": "new_clip_id",
"song_title": "Версия кавера",
"status": "pending"
}
]
}
}
Большие файлы и обрезанные запросы
Рекомендуется: разделить загрузку и кавер на два шага
Одноразовый эндпоинт (этот) объединяет загрузку и генерацию в один шаг: большое тело находится именно в этом единственном шаге, поэтому при обрыве неясно ни сгенерировалось ли что-то, ни было ли списание.
| Шаг 1 загрузка | Шаг 2 кавер | |
|---|---|---|
| Эндпоинт | POST /api/music/upload-source |
POST /api/music/generate-from-source |
| Оплата | Бесплатно (только загрузка, без генерации) | 0,6 ¥ за вызов; 1,2 ¥ за вызов с Max Mode |
| Тело запроса | Само аудио (base64 / multipart) или только ссылка через file_url |
Около 250 байт (только один sourceClipId) |
| Возвращает | clip_id (ID клипа исходного аудио) |
data.clips[].song_id (результат генерации) |
| Если не получилось | Просто повторите, без списания и без задачи генерации | Тайм-аут клиента ≥300 с; при тайм-ауте сначала проверьте через /api/music/songs и не повторяйте сразу |
| Переиспользование исходника | Тот же clip_id годится и для продления / замены / разделения |
Аудио нужно загружать заново каждый раз |
Вывод: аудио больше примерно 8 МБ, нестабильная сеть или один материал на несколько использований → двухшаговая форма; крошечное аудио в стабильной сети → этот эндпоинт проще.
Что означает 400 unexpected end of JSON input
Это значит, что JSON, полученный сервером, неполон (это не ошибка в параметрах, не проблема прав или баланса). Обычные причины, от наиболее вероятной:
- Большое тело обрезано в середине передачи: входной слой фиксирует и «сколько байт объявил клиент», и «сколько реально пришло». Измеренный случай: клиент объявил 14,17 МБ, а пришло только 11,8–12,4 МБ, и все три запроса остановились примерно на 1,6–1,7 с; недостающее число байт каждый раз было разным, что указывает на обрыв передачи, а не на фиксированный лимит (сервер не ограничивает размер тела запроса).
Content-Lengthне совпадает с реально отправленными байтами: в Node.js использование.lengthстроки (число символов UTF-16) в качестве длины даёт ошибку, как только в содержимом появляется китайский или другой многобайтовый текст.- Тело записано строкой, а не Buffer, поэтому записанные байты не совпадают с объявленными.
Все три случая происходят до списания, поэтому расходов не возникает.
Самопроверка на стороне клиента
-
Content-Lengthберётся изBuffer.byteLength(json, 'utf8')(илиBuffer.from(json).length) — никогда изjson.length; - Тело запроса записывается как Buffer, а не как строка;
- Тайм-аут сокета / запроса ≥ 300 секунд;
- Если аудио больше примерно 8 МБ: используйте
file_url(тело всего несколько сотен байт), либо multipart-загрузкуupload-source, либо сразу двухшаговую форму; - В multipart-запросах не задавайте
Content-Typeвручную (boundary должен добавить клиент); - Выведите «сколько байт реально отправлено» и сравните с
Content-Length; - В двухшаговой форме убедитесь, что шаг 1 вернул
clip_idиstatusв завершённом состоянии, и только затем отправляйте шаг 2.
Частые ошибки
| Ошибка | Значение | Что делать |
|---|---|---|
unexpected end of JSON input |
Тело запроса неполное (обрезано) | Пройдите самопроверку выше или перейдите на двухшаговую форму |
invalid character '-' in numeric literal |
Multipart-тело отправлено на JSON-эндпоинт | Не используйте multipart на JSON-эндпоинтах и не задавайте Content-Type вручную |
one of file_path, file_base64, file_url, or multipart file is required |
Аудио не приложено | Добавьте file_base64 / file_url / multipart-file |
model is required |
Тело — пустой корректный JSON (например {}) |
Передайте хотя бы model |
Invalid request: Invalid request, ... |
Обёртка о неудачном разборе тела | Смотрите вторую половину с конкретной причиной (обычно одна из перечисленных) |
Связанные эндпоинты: API загрузки исходного аудио (шаг 1), API кавера по исходному клипу (шаг 2).
Получить API-ключ
Создайте API-ключ в консоли после регистрации. Одна генерация стоит 0,6 ¥ и возвращает 2 трека, загрузки не ограничены, номер телефона не нужен.
Получить API-ключ Вернуться к обзору