# Persona
> 从已有歌曲里提取可复用的歌手人设，异步任务
> 之后生成新歌时绑定这个人设，沿用其音色与风格
> 结果在 `result.persona_id`
`POST /v1/music/generations/persona`
## 认证
- `Authorization` (string / 必填) — 所有接口均使用 Bearer Token 进行认证。 获取 API Key：[访问控制台](https://api.oairoute.com/keys) 创建。 请求时在请求头中添加： ```http Authorization: Bearer YOUR_OAIRoute_KEY ```
## 引用源音轨
- `task_id` (string / 必填) — 产出源音轨那次任务的 task_id。缺失或无法解析源音轨时，提交阶段直接返回 400。
- `audio_index` (integer / 可选) — 指定 `result.music[]` 中第几首作为源音轨，默认 `1`。一次生成通常为 1 或 2。
## 请求参数
- `model` (string / 可选) — 音频模型，默认 `suno`，当前仅 `suno`。
- `name` (string / 必填) — Persona 名称。缺失时直接返回 400。
- `describe` (string / 可选) — 描述这个人设的特点。
- `styles` (string / 可选) — 风格标签。
- `vocal_start_s` (number / 可选) — 人声片段的起点，单位秒，不小于 0。
- `vocal_end_s` (number / 可选) — 人声片段的终点，单位秒。须大于 `vocal_start_s`，且不超过已知源时长。
本端点没有版本维度，传 `version` 会被忽略，也不影响计费。
## 人声片段怎么取
`vocal_start_s` 与 `vocal_end_s` 用来指定从哪一段人声里提取特征。建议成对提供：
- 只给起点不给终点，容易把整段都算进去，包含器乐部分
- 区间太长，特征会被多种唱法稀释
- 理想的区间是 10 到 30 秒的纯人声，没有伴奏干扰
## 响应
- `code` (integer) — 响应状态码。
- `data[].status` (string) — 提交后为 `submitted`。
- `data[].task_id` (string) — 任务唯一标识，用于轮询。
轮询用 `GET /v1/music/tasks/{task_id}`，间隔 3 到 5 秒，典型耗时 30 到 120 秒。结果里的 `result.persona_id` 就是最终的人设标识。
失败时 `data.error.message` 给出原因，预扣额度自动退回。
## 拿到 persona_id 之后
在生成、翻唱、续写时传 `persona_id` 即可沿用这个人设：
```json
{
  "model": "suno",
  "custom": true,
  "version": "v6",
  "persona_id": "persona_01KA",
  "prompt": "[Verse]\n新的歌词",
  "tags": "city pop"
}
```
> **Note:** 
> `persona_id` 与 `custom_model_id` 互斥，两者不能同时传。它们代表两种不同的复用方式：Persona 复用音色与演唱风格，自定义模型复用整体曲风。
> **Note:** 
> `persona_id` 与自定义模型 ID 不同，**不能作为 API 的 `model` 值使用**。它只能填在 `persona_id` 字段里。新流程也不需要先创建 Vox。
## 错误码
错误响应的格式、状态码与重试建议见[错误码与限流](../../../support/errors.html)，常见报错的排查步骤见[常见问题](../../../support/faq.html)。
## 使用示例
提交一个任务并拿到 `task_id`：
> **Note:** 
> 提交成功只表示任务已受理。真正的产物要拿返回的 `task_id` 去任务查询接口轮询，`status` 变成 `completed` 之后才有结果。
**Persona::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/persona' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "suno",
    "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K",
    "audio_index": 1,
    "name": "深夜女声",
    "describe": "气声偏多，尾音轻，适合慢歌",
    "styles": "city pop, female vocal",
    "vocal_start_s": 8,
    "vocal_end_s": 32
  }'
```
**Persona::Python**
```
import requests
res = requests.post(
    "https://api.oairoute.com/v1/music/generations/persona",
    headers={
        "Authorization": "Bearer YOUR_OAIRoute_KEY",
        "Content-Type": "application/json",
    },
    json={
        "model": "suno",
        "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K",
        "audio_index": 1,
        "name": "深夜女声",
        "vocal_start_s": 8,
        "vocal_end_s": 32,
    },
)
print(res.json()["data"][0]["task_id"])
```
**Persona::JavaScript**
```
const url = "https://api.oairoute.com/v1/music/generations/persona";
const options = {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K",
    "audio_index": 1,
    "name": "深夜女声",
    "describe": "气声偏多，尾音轻，适合慢歌",
    "styles": "city pop, female vocal",
    "vocal_start_s": 8,
    "vocal_end_s": 32
  }),
};
fetch(url, options)
  .then((res) => res.json())
  .then((json) => console.log(json))
  .catch((err) => console.error(err));
```
**200 Persona**
```
{
  "code": 200,
  "data": {
    "id": "task_01K8C77M0HP1GJWBJYZMKX1XS1",
    "status": "completed",
    "progress": 100,
    "created": 1763088289,
    "completed": 1763088371,
    "actual_time": 82,
    "cost": 0.024,
    "credits_cost": 0.24,
    "result": {
      "persona_id": "persona_01KA",
      "name": "深夜女声"
    }
  }
}
```
