# 音乐延伸
> 对已有音频续写，异步任务
> 用 `clip_id` 引用源音频，指定起点与时长
> 产出的是**新的** clip_id，后续操作要用新值
`POST /v1/music/generations/extendFlowMusic`
## 认证
- `Authorization` (string / 必填) — 所有接口均使用 Bearer Token 进行认证。 获取 API Key：[访问控制台](https://api.oairoute.com/keys) 创建。 请求时在请求头中添加： ```http Authorization: Bearer YOUR_OAIRoute_KEY ```
## 请求参数
- `model` (string / 必填) — 固定填 `flowmusic`，大小写不敏感。
- `clip_id` (string / 必填) — 源音频标识，取自成功任务的 `result.music[].clip_id`。 源任务必须已完成。外部音频需先调「上传音频」接口换取 clip_id。
- `extend_from_s` (number / 必填) — 从第几秒开始续写。**不能超过源 clip 的实际时长**，超出返回 400。
- `extend_s` (number / 必填) — 续写时长，单位秒。**上限 164 秒**，超出返回 400。
- `instruction` (string / 必填) — 续写编辑指令。例如「延续主歌旋律，加入弦乐」。
- `title` (string / 可选) — 续写后作品的标题。
- `seed` (string / 可选) — 随机种子，用于复现结果。
## 结果字段
- `result.music[].clip_id` (string) — **新的**音频标识。后续再做延伸或分轨时要用这个新值，不是原来的 clip_id。
- `result.music[].title` (string) — 标题，未指定时形如 `Untitled (Extended)`。
- `result.music[].duration_seconds` (string) — 时长，**字符串形式的浮点秒数**，例如 `"39.95733333"`。
- `result.music[].audio_url` (string) — 音频地址，`.m4a`。
- `result.music[].wav_url` (string) — WAV 格式地址。
- `result.music[].image_url` (string) — 封面图地址。
- `result.music[].lyrics_timing_markers` (array) — 时间轴标记，元素为 `[时间, 值]` 二元数组。
## 两个数值上限
| 字段 | 上限 | 超限结果 |
|---|---|---|
| `extend_from_s` | 源 clip 的实际时长 | 400 |
| `extend_s` | 164 秒 | 400 |
`extend_from_s` 的上限不是固定值，取决于源音频多长。所以要先查一次源任务，拿到 `duration_seconds` 再决定起点。
> **Note:** 
> `duration_seconds` 是字符串。做比较前要先转成浮点数，否则 `"39.9" > 40` 这种字符串比较会给出错误结果。
## 错误码
错误响应的格式、状态码与重试建议见[错误码与限流](../../../support/errors.html)，常见报错的排查步骤见[常见问题](../../../support/faq.html)。
## 使用示例
提交一个任务并拿到 `task_id`：
> **Note:** 
> 提交成功只表示任务已受理。真正的产物要拿返回的 `task_id` 去任务查询接口轮询，`status` 变成 `completed` 之后才有结果。
**音乐延伸{Extend music}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/v1/music/generations/extendFlowMusic' \
  --header 'Authorization: Bearer YOUR_OAIRoute_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "flowmusic",
    "clip_id": "c_01KA",
    "extend_from_s": 30,
    "extend_s": 60,
    "instruction": "延续主歌旋律，加入弦乐"
  }'
```
**音乐延伸{Extend music}::Python**
```
import requests
res = requests.post(
    "https://api.oairoute.com/v1/music/generations/extendFlowMusic",
    headers={
        "Authorization": "Bearer YOUR_OAIRoute_KEY",
        "Content-Type": "application/json",
    },
    json={
        "model": "flowmusic",
        "clip_id": "c_01KA",
        "extend_from_s": 30,
        "extend_s": 60,
        "instruction": "延续主歌旋律，加入弦乐",
    },
)
print(res.json()["data"][0]["task_id"])
```
**音乐延伸{Extend music}::JavaScript**
```
const url = "https://api.oairoute.com/v1/music/generations/extendFlowMusic";
const options = {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_OAIRoute_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "model": "flowmusic",
    "clip_id": "c_01KA",
    "extend_from_s": 30,
    "extend_s": 60,
    "instruction": "延续主歌旋律，加入弦乐"
  }),
};
fetch(url, options)
  .then((res) => res.json())
  .then((json) => console.log(json))
  .catch((err) => console.error(err));
```
**200 音乐延伸{Extend music}**
```
{
  "code": 200,
  "data": [
    { "status": "submitted", "task_id": "task_01K8B00M0HP1GJWBJYZMKX1XS1" }
  ]
}
```
