# Свои материалы

> Элементы Kling, свои голоса, стили и персонажи (ElevenLabs, Recraft, Eleven Music, Gemini Omni, Suno), исполнители Suno и помощники формы.

## <a id="kling-elements"></a>Элементы Kling

Элемент это сохранённый персонаж, животное, предмет, костюм, место или эффект. Kling 3.0 и 4.0 Omni держат его одинаковым во всех сценах и роликах. Элементы общие для всех входов человека: кабинета сайта, приложения и мини-приложения в Telegram и MAX. Создание бесплатное.

```bash
curl "https://api.cyhub.ai/v1/models/kling_pro/elements" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

response = requests.get(f"{API}/models/kling_pro/elements", headers=HEADERS, timeout=30)
response.raise_for_status()
library = response.json()
for element in library["elements"]:
    print(element["label"], element["name"], element["tag"])
```

В ответе elements (у каждого id, label, name, description, tag, type, cover_url), tags (виды элементов: key для запроса, name для человека и views, с каких сторон стоит снять объект) и limits (длина имени и описания, сколько картинок, какие файлы принимает Kling).

## <a id="create"></a>Создать элемент

Из картинок: image_urls, до четырёх прямых ссылок. Первая картинка это обложка, остальные тот же объект с других сторон. Из видео: video_url, одна ссылка на короткое видео персонажа, только с тегом character. Если ссылок нет, сначала загрузите файлы в POST /v1/files.

```bash
curl -X POST "https://api.cyhub.ai/v1/models/kling_pro/elements" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "name": "Alice",
  "description": "A girl in a red coat with a short bob",
  "tag": "character",
  "image_urls": [
    "https://example.com/alice-front.jpg",
    "https://example.com/alice-side.jpg"
  ]
}'
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

body = {
  "name": "Alice",
  "description": "A girl in a red coat with a short bob",
  "tag": "character",
  "image_urls": [
    "https://example.com/alice-front.jpg",
    "https://example.com/alice-side.jpg"
  ]
}
headers = HEADERS
response = requests.post(f"{API}/models/kling_pro/elements", json=body, headers=headers, timeout=60)
response.raise_for_status()
element = response.json()
print(element["label"])
```

Kling создаёт элемент, пока запрос ждёт: обычно меньше минуты, иногда несколько минут, поэтому держите таймаут запроса не меньше пяти минут. Ответ 201 с элементом в том же виде, что в списке. Файлы уходят в Kling как есть: то, что он не примет, вернётся ответом 502 element_create_failed. Имя у человека не повторяется: 409 element_name_taken.

## <a id="use"></a>Вставить в видео

Напишите label элемента (Element_<id>) в описании ролика prompt или в описании сцены в shots. Отделяйте метку от соседних слов пробелом или знаком препинания. Элементы работают у Kling 3.0 и 4.0 Omni (model_version v3.0 и v4.0-omni) и в цену не входят. У «Кадров» 4.0 (v4.0) элементов нет.

```json
{
  "model": "kling_pro",
  "settings": {
    "model_version": "v3.0",
    "prompt": "Element_284716395 walks through the night city in the rain, the camera follows from the side",
    "length": 5
  }
}
```

Элемента нет среди ваших (удалён или чужой): задача не ставится, ответ 422 element_not_found, деньги не резервируются.

[Параметры Kling 3.0](https://api.cyhub.ai/models/kling-3/api.md)

## <a id="scenes"></a>Свои сцены

Ролик Kling 3.0 можно разрезать на сцены самому: multi_shot: true и список shots, от 2 до 6 сцен, у каждой prompt и duration в целых секундах. Сумма длительностей равна length. Общее описание prompt тогда не передаётся. В описаниях сцен работают метки элементов.

```json
{
  "model": "kling_pro",
  "settings": {
    "model_version": "v3.0",
    "multi_shot": true,
    "length": 10,
    "shots": [
      {
        "prompt": "Element_284716395 finds an old map in the attic",
        "duration": 4
      },
      {
        "prompt": "Element_284716395 runs with the map across a field to the lighthouse",
        "duration": 6
      }
    ]
  }
}
```

## <a id="delete"></a>Удалить элемент

```bash
curl -X DELETE "https://api.cyhub.ai/v1/models/kling_pro/elements/ELEMENT_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

response = requests.delete(f"{API}/models/kling_pro/elements/ELEMENT_ID", headers=HEADERS, timeout=60)
response.raise_for_status()
```

Ответ 204. Ролики, уже сделанные с элементом, остаются как есть.

## <a id="suno-personas"></a>Исполнители Suno

Исполнитель это манера и голос из версии готовой песни Suno. Сохраните его, и новые песни будут петься в той же манере и похожим голосом. В списке исполнители со всех ваших входов: сохранённые через API и в мини-приложении Telegram и MAX. Сохранение бесплатное.

```bash
curl "https://api.cyhub.ai/v1/models/suno/personas" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

response = requests.get(f"{API}/models/suno/personas", headers=HEADERS, timeout=30)
response.raise_for_status()
library = response.json()
for persona in library["personas"]:
    print(persona["id"], persona["name"], persona["song_title"])
```

В ответе personas (у каждого id, name, description, style и song_title, название песни, из которой он сохранён) и limits (длина имени, описания и стиля).

## <a id="persona-create"></a>Сохранить исполнителя

Нужны id готовой задачи Suno (source_task_id), index версии песни в её result.artifacts, имя name и описание description. Стиль style по желанию. Из одной версии песни сохраняется один исполнитель, у звуков (режим sounds) исполнителя нет.

```bash
curl -X POST "https://api.cyhub.ai/v1/models/suno/personas" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "source_task_id": "TASK_ID",
  "index": 0,
  "name": "Night Driver",
  "description": "A low male voice, calm and husky, synthwave",
  "style": "synthwave, retro"
}'
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

body = {
  "source_task_id": "TASK_ID",
  "index": 0,
  "name": "Night Driver",
  "description": "A low male voice, calm and husky, synthwave",
  "style": "synthwave, retro"
}
headers = HEADERS
response = requests.post(f"{API}/models/suno/personas", json=body, headers=headers, timeout=60)
response.raise_for_status()
persona = response.json()
print(persona["id"])
```

Suno сохраняет исполнителя, пока запрос ждёт. Ответ 201 с исполнителем в том же виде, что в списке. Исполнитель из этой версии уже есть: 409 persona_exists. Suno не сохранил: 502 persona_create_failed, повторите через минуту.

## <a id="persona-use"></a>Песня с исполнителем

Передайте id исполнителя в поле persona режимов generate, cover_upload и extend. Исполнитель в цену не входит.

```json
{
  "model": "suno",
  "settings": {
    "mode": "generate",
    "songDescription": "A calm night song about an empty highway",
    "persona": "PERSONA_ID"
  }
}
```

Исполнителя нет среди ваших (не сохранён или чужой): задача не ставится, ответ 422 persona_not_found, деньги не резервируются.

[Параметры Suno](https://api.cyhub.ai/models/suno/api.md)

## <a id="own-materials"></a>Голоса, стили и персонажи

Так же, как элементы, устроены свои голоса, стили и персонажи других моделей: список GET, создание POST, удаление DELETE по адресу библиотеки модели. Материалы общие для всех ваших входов, создание бесплатное. Файлы передаются прямыми ссылками (свои файлы сначала загрузите в POST /v1/files) и уходят в сервис как есть: что он не примет, вернётся ответом 502. id материала идёт в поле генерации, которое названо ниже; чужой, удалённый или ещё не готовый материал получает отказ до списания.

| Библиотека | Поле генерации | Что это |
|---|---|---|
| `/v1/models/elevenlabs/voices` | voice, voice_2…voice_20 | Клон вашего голоса по записям: озвучка текста и смена голоса. |
| `/v1/models/recraft/styles` | style_id | Стиль из 1-10 ваших картинок. Линия raster для картинок, vector для SVG. Движки V4 Styles работают только со своим стилем. |
| `/v1/models/elevenlabs_music/styles` | style | Стиль, обученный на ваших треках: учится 5-10 минут, в генерацию идёт со статусом ready. |
| `/v1/models/gemeni_omni/characters` | character_ids | Персонаж по портрету и снимку в полный рост, до трёх в ролике. |
| `/v1/models/gemeni_omni/voices` | audio_ids | Свой голос на основе готового, до трёх в ролике вместе с готовыми. |
| `/v1/models/suno/voices` | voice | Ваш певческий голос: делается по шагам, ниже. |

```bash
curl -X POST "https://api.cyhub.ai/v1/models/elevenlabs/voices" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "name": "My voice",
  "sample_urls": [
    "https://example.com/voice-1.mp3",
    "https://example.com/voice-2.mp3"
  ],
  "remove_background_noise": true
}'
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

body = {
  "name": "My voice",
  "sample_urls": [
    "https://example.com/voice-1.mp3",
    "https://example.com/voice-2.mp3"
  ],
  "remove_background_noise": true
}
headers = HEADERS
response = requests.post(f"{API}/models/elevenlabs/voices", json=body, headers=headers, timeout=60)
response.raise_for_status()
voice = response.json()
print(voice["id"])
```

```json
{
  "model": "elevenlabs",
  "settings": {
    "mode": "text_to_dialogue",
    "text": "Hello! This is my own voice.",
    "voice": "VOICE_ID"
  }
}
```

Пределы и правила каждой библиотеки в её ответе GET, поле limits. Создание стиля Recraft, голоса ElevenLabs и персонажа Gemini Omni идёт, пока запрос ждёт: держите таймаут не меньше пяти минут. Стиль Eleven Music отвечает сразу со статусом training.

## <a id="suno-voices"></a>Свой голос Suno

Голос делается по шагам. 1: POST /v1/models/suno/voices с прямой ссылкой на запись вашего пения source_url, границами куска start_seconds и end_seconds (от 10 до 240 секунд) и языком. 2: опрашивайте GET /v1/models/suno/voices/{id}, пока status не станет pending_recording: в поле phrase фраза, которую нужно спеть. 3: POST /v1/models/suno/voices/{id}/verify со ссылкой на запись этой фразы тем же голосом recording_url и именем name. 4: опрашивайте до status ready, после этого id идёт в поле voice песни. Не вышло (failed, поле error): POST /v1/models/suno/voices/{id}/retry даст новую фразу по той же записи.

```json
{
  "model": "suno",
  "settings": {
    "mode": "generate",
    "songDescription": "A warm acoustic song about the sea",
    "voice": "VOICE_ID"
  }
}
```

Голос вместе с исполнителем (persona) не передаётся. Голоса у Suno бывают недолговечны: задача с пропавшим голосом получает отказ без списания.

## <a id="helpers"></a>Помощники формы

Бесплатные подсказки, как кнопки приложения: POST /v1/models/suno/lyrics с идеей песни prompt вернёт несколько вариантов текста (title и text), POST /v1/models/suno/style-boost с коротким стилем style вернёт подробный стиль, POST /v1/models/recraft/enhance с описанием prompt вернёт описание подробнее. Не больше 20 обращений в час на кабинет, дальше 429 rate_limited.

```bash
curl -X POST "https://api.cyhub.ai/v1/models/suno/lyrics" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
  "prompt": "a cheerful song about a lazy cat"
}'
```

```python
import requests

API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

body = {
  "prompt": "a cheerful song about a lazy cat"
}
headers = HEADERS
response = requests.post(f"{API}/models/suno/lyrics", json=body, headers=headers, timeout=60)
response.raise_for_status()
for variant in response.json()["variants"]:
    print(variant["title"])
    print(variant["text"])
```
