# 上传音频并延伸
> 上传一段音频并在其后续写，一步完成，异步任务
> 与「续写延长」不同：这里直接收 `audio_url`，不用 task_id
> 固定为自定义模式，无需先调上传接口
`POST /v1/music/generations/uploadExtend`
## 认证
- `Authorization` (string / 必填) — 所有接口均使用 Bearer Token 进行认证。 获取 API Key：[访问控制台](https://api.oairoute.com/keys) 创建。 请求时在请求头中添加： ```http Authorization: Bearer YOUR_OAIRoute_KEY ```
## 请求参数
- `model` (string / 可选) — 仅支持 `suno`，默认也是 `suno`。
- `audio_url` (string / 必填) — 需为公网可访问的 HTTP(S) 音频直链，建议不超过 8 分钟。 本地路径与 `blob:` URL 不可用。
- `continue_at` (number / 必填) — 延伸起点。需**大于等于 1 秒**，且**严格小于源音频实际时长**。
- `version` (string / 可选) — 可选 `v6`（默认）、`v6-wild`、`v6-mini`。使用 `custom_model_id` 时省略。
- `custom_model_id` (string / 可选) — 模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。
- `prompt` (string / 可选) — 延伸段歌词，最多 5000 字符。**不传则按纯音乐语义处理**。
- `tags` (string / 可选) — 风格描述，最多 1000 字符。
- `title` (string / 可选) — 标题，最多 80 字符。
- `negative_tags` (string / 可选) — 排除的风格。
- `style_weight` (number / 可选) — 取值范围 0 到 1。
- `weirdness` (number / 可选) — 取值范围 0 到 1。
- `audio_weight` (number / 可选) — 取值范围 0 到 1。
- `auto_lyrics` (boolean / 可选) — 是否对输入歌词二次创作。
- `vocal_gender` (string / 可选) — `Male` 或 `Female`。
- `persona_id` (string / 可选) — 与 `custom_model_id` 互斥。
- `duration_s` (integer / 可选) — 目标时长 10 到 360 秒。实际时长以任务结果为准。
- `variety` (string / 可选) — `off`、`normal`、`high`、`extra`、`max`。
- `max_mode` (boolean / 可选) — 启用后按普通售价 2 倍计费，默认 `false`。
- `audio_format` (string / 可选) — `mp3`、`m4a` 或 `wav`。
## 与其他接口的分工
| 接口 | 输入 | 是否需要先上传 |
|---|---|---|
| 续写延长 | `task_id` + `audio_index` | 是 |
| **上传并延伸（本页）** | **`audio_url` + `continue_at`** | **否** |
| 上传音频 | `audioFilePath` | — |
本接口把「上传」与「延伸」合成一步。省一次调用，也省一个中间状态要等。
## 固定为自定义模式
接口**固定为自定义模式**，所以：
- 不需要传 `custom` 字段
- 不要传 `instrumental`
- 不要传 `gpt_description`
传了这三个字段也不会生效，属于无效参数。
> **Note:** 
> `prompt` 不传时会按纯音乐语义处理。想要有人声演唱，必须给歌词。
## 响应
- `code` (integer) — 响应状态码。
- `data` (array) — 提交结果。取 `data[0].task_id` 轮询任务查询接口。
- `data[].status` (string) — 示例值 `submitted`。
- `data[].task_id` (string) — 任务标识，用于轮询。
## continue_at 的边界
这是本接口最容易出错的地方，两个边界都不能踩：
| 边界 | 规则 |
|---|---|
| 下界 | 大于等于 1 秒 |
| 上界 | 严格小于源音频实际时长 |
> **Note:** 
> 上界是**源音频**的时长，不是你想续写到多长。想续写 60 秒的内容，`continue_at` 依然受源音频时长约束。
## 错误码
错误响应的格式、状态码与重试建议见[错误码与限流](../../../support/errors.html)，常见报错的排查步骤见[常见问题](../../../support/faq.html)。
## 使用示例
### 从上传音频续写
`continue_at` 指定从第几秒开始接续，必须大于等于 1 秒且小于源音频总时长。音频同样要走公网地址。
### 指定风格与标题
接了 `prompt` 之后，续写部分会沿用前面的调性，同时往提示词描述的方向走。想要新段落有明确标签，把 `tags` 一起传。
### 接着已有任务续写
如果源音频来自本平台生成的任务，直接用生成类接口的 `extend`，不必先导出再上传。
**上传音频并延伸{Upload and extend}::cURL**
```
curl -X POST https://api.oairoute.com/v1/music/generations/uploadExtend \
  -H 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  -H 'Content-Type: application/json' \
  --data '{
    "model": "suno",
    "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
    "continue_at": 118.5,
    "prompt": "[Verse]\n风还在吹",
    "tags": "folk, warm",
    "duration_s": 60
  }'
```
**上传音频并延伸{Upload and extend}::Python**
```
import requests
res = requests.post(
    "https://api.oairoute.com/v1/music/generations/uploadExtend",
    headers={
        "Authorization": "Bearer YOUR_OAIRoute_KEY",
        "Content-Type": "application/json",
    },
    json={
        "model": "suno",
        "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
        "continue_at": 118.5,
        "prompt": "[Verse]\n风还在吹",
        "tags": "folk, warm",
        "duration_s": 60,
    },
)
print(res.json()["data"][0]["task_id"])
```
**上传音频并延伸{Upload and extend}::JavaScript**
```
const url = "https://api.oairoute.com/v1/music/generations/uploadExtend";
const options = {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
    "continue_at": 118.5,
    "prompt": "[Verse]\n风还在吹",
    "tags": "folk, warm",
    "duration_s": 60
  }),
};
fetch(url, options)
  .then((res) => res.json())
  .then((json) => console.log(json))
  .catch((err) => console.error(err));
```
**200 上传音频并延伸{Upload and extend}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8F88M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
**纯音乐延伸{Instrumental extension}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/uploadExtend' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "suno",
  "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
  "continue_at": 60,
  "tags": "ambient, piano",
  "duration_s": 45
}'
```
**纯音乐延伸{Instrumental extension}::Python**
```
import requests
url = "https://api.oairoute.com/v1/music/generations/uploadExtend"
headers = {
    "Authorization": "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
}
payload = {
      "model": "suno",
      "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
      "continue_at": 60,
      "tags": "ambient, piano",
      "duration_s": 45
    }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**纯音乐延伸{Instrumental extension}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/music/generations/uploadExtend", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "audio_url": "https://your-bucket.s3.amazonaws.com/base.mp3",
    "continue_at": 60,
    "tags": "ambient, piano",
    "duration_s": 45
  }),
});
console.log(await res.json());
```
**200 纯音乐延伸{Instrumental extension}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8F88M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
**从上传音频续写{Continue from upload}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/uploadExtend' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "suno",
    "audio_url": "https://example.com/segment.mp3",
    "continue_at": 45,
    "prompt": "延续前面的旋律，加入弦乐铺底",
    "version": "v6"
  }'
```
**从上传音频续写{Continue from upload}::Python**
```
import requests
url = "https://api.oairoute.com/v1/music/generations/uploadExtend"
headers = {"Authorization": "Bearer YOUR_OAIRoute_KEY"}
payload = {
    "model": "suno",
    "audio_url": "https://example.com/segment.mp3",
    "continue_at": 45,
    "prompt": "延续前面的旋律，加入弦乐铺底",
    "version": "v6"
  }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**从上传音频续写{Continue from upload}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/music/generations/uploadExtend", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "audio_url": "https://example.com/segment.mp3",
    "continue_at": 45,
    "prompt": "延续前面的旋律，加入弦乐铺底",
    "version": "v6"
  }),
});
console.log(await res.json());
```
**指定风格与标题{With style and title}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/uploadExtend' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "suno",
    "audio_url": "https://example.com/intro.mp3",
    "continue_at": 30,
    "prompt": "副歌部分，情绪推进",
    "title": "夏末（续）",
    "tags": "pop, uplifting",
    "version": "v6"
  }'
```
**指定风格与标题{With style and title}::Python**
```
import requests
url = "https://api.oairoute.com/v1/music/generations/uploadExtend"
headers = {"Authorization": "Bearer YOUR_OAIRoute_KEY"}
payload = {
    "model": "suno",
    "audio_url": "https://example.com/intro.mp3",
    "continue_at": 30,
    "prompt": "副歌部分，情绪推进",
    "title": "夏末（续）",
    "tags": "pop, uplifting",
    "version": "v6"
  }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**指定风格与标题{With style and title}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/music/generations/uploadExtend", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "audio_url": "https://example.com/intro.mp3",
    "continue_at": 30,
    "prompt": "副歌部分，情绪推进",
    "title": "夏末（续）",
    "tags": "pop, uplifting",
    "version": "v6"
  }),
});
console.log(await res.json());
```
**接着已有任务续写{Continue existing task}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/extend' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "suno",
    "task_id": "task_01K8D77M0HP1GJWBJYZMKX1XS1",
    "continue_at": 60,
    "prompt": "延续前面的旋律"
  }'
```
**接着已有任务续写{Continue existing task}::Python**
```
import requests
url = "https://api.oairoute.com/v1/music/generations/extend"
headers = {"Authorization": "Bearer YOUR_OAIRoute_KEY"}
payload = {
    "model": "suno",
    "task_id": "task_01K8D77M0HP1GJWBJYZMKX1XS1",
    "continue_at": 60,
    "prompt": "延续前面的旋律"
  }
res = requests.post(url, headers=headers, json=payload)
print(res.json())
```
**接着已有任务续写{Continue existing task}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/v1/music/generations/extend", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "suno",
    "task_id": "task_01K8D77M0HP1GJWBJYZMKX1XS1",
    "continue_at": 60,
    "prompt": "延续前面的旋律"
  }),
});
console.log(await res.json());
```
**200 从上传音频续写{Continue from upload}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8F88M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
**200 指定风格与标题{With style and title}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8F88M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
**200 接着已有任务续写{Continue existing task}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8F88M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
