feat(seedance): 加 generate_audio 参数对齐官方 API
火山方舟官方 curl 例子 (CreateContentsGenerationsTasks) body 里有 generate_audio 字段 — Seedance 2.0 旗舰特性,原生 AI 生成背景音 / 角色对白 / 音效。我之前没接,补上。 - yaml 加 default_generate_audio: false (控成本默认关) - tool execute 加 generate_audio kw + 进 body / meta / usage_events extra_units - tool banner 加 audio=<bool> 字段 - SKILL 加参数段说明 + prompt 写法变化 (开音轨时要写背景音/对白具体内容) + 贴 prompt 模板 + 反模式各加一条 resolution / watermark 官方例子里没发但其他文档源确认 fast 必传 + 有效,保留。 参考媒体 (image_url/video_url/audio_url + role:reference_*) 是 i2v/v2v/r2v 路径, phase 1 不接,延后。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d3a93fc1f
commit
da71daa789
|
|
@ -52,6 +52,10 @@ video:
|
|||
default_ratio: "16:9" # 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9 / adaptive
|
||||
default_duration: 5 # 4-15s
|
||||
default_watermark: false
|
||||
# generate_audio: Seedance 2.0 旗舰特性 —— 原生 AI 生成背景音效 / 角色对白(无需后期配音)。
|
||||
# 开启会增加 token 消耗(模型还要算音轨),cost 比纯视频高;默认关闭让 cost 可预测,
|
||||
# 用户要带音的视频(广告 / 角色对白)时显式传 true。
|
||||
default_generate_audio: false
|
||||
|
||||
# 轮询参数
|
||||
request_timeout_s: 60 # submit POST 超时(异步,只是提交)
|
||||
|
|
|
|||
|
|
@ -115,11 +115,12 @@ description: 用豆包 Seedance 2.0 Fast 生视频(`seedance` tool)。**任何
|
|||
> ratio: 16:9(ppt 横版)
|
||||
> duration: 5 秒
|
||||
> watermark: false
|
||||
> generate_audio: false(静音视频,后期 ppt 加 BGM)
|
||||
> 预计花费: ¥4.00
|
||||
> 预计等待: 30-90 秒
|
||||
> ````
|
||||
>
|
||||
> 这样开烧?要改什么?(改 prompt 文字 / 改时长 / 换比例 / 降到 480p 省钱)
|
||||
> 这样开烧?要改什么?(改 prompt 文字 / 改时长 / 换比例 / 降到 480p 省钱 / 开 audio 加 AI 配音)
|
||||
|
||||
然后 ⛔ **BLOCKING:等用户明确回复**。
|
||||
|
||||
|
|
@ -169,6 +170,21 @@ description: 用豆包 Seedance 2.0 Fast 生视频(`seedance` tool)。**任何
|
|||
|---|---|
|
||||
| `false` | 默认无水印(申报 / ppt / 客户交付都不该带);仅当用户明确说"加水印"才传 `true` |
|
||||
|
||||
### `generate_audio`(Seedance 2.0 旗舰特性)
|
||||
|
||||
| 默认 | 何时开 |
|
||||
|---|---|
|
||||
| `false` | 默认关 —— 控成本 + 大多数 ppt / 申报场景用静音视频(后期配音 / 当背景视频)。**模型还要算音轨,开启 cost 会高于纯视频估算**(具体增幅未实测,首次开时盯一下返回的 tokens)。 |
|
||||
| `true` | 用户明确要**带声音的视频**:广告 / 短剧 / 角色对白 / 配乐场景。**调用前必须告诉用户**"开启 audio,cost 会高于估算 ¥X"并等确认。 |
|
||||
|
||||
prompt 写法变化:开 `generate_audio=true` 时,prompt 里要描述**声音是什么**(背景音 / 音效 / 对白台词具体说啥 / 音色),否则模型随机配,效果难控:
|
||||
|
||||
```
|
||||
... 背景音「鲜切现摇」,女生音色,轻快鼓点卡点
|
||||
```
|
||||
|
||||
参考火山方舟官方 r2v 例子(`r2v_tea_*`):每个镜头段都明示"背景音 XX / 卡点 XX / 音效 XX"。**不写 = 不可预期**。
|
||||
|
||||
## 调用范式
|
||||
|
||||
**前置条件**:用户已经看过最终 prompt + 所有参数,明确回复"可以" / "OK" / "出片吧" 之类。**没看到这个确认就不要调**。
|
||||
|
|
@ -232,6 +248,7 @@ seedance(
|
|||
- ❌ prompt 里写否定 "no shaking, not blurry" —— Seedance 不支持 negative,反向起效
|
||||
- ❌ 让用户在 seedream / seedance 之间默默替他决定 —— 模糊就一句话问明白
|
||||
- ❌ phase 1 拿用户已生成的图试图 i2v —— **当前不支持**,明确告诉用户
|
||||
- ❌ 用户没说要声音就把 `generate_audio` 设 true —— 多花钱且大概率配出不合用户预期的随机音效;开它前必须问"要 AI 配音吗?cost 会高于估算"
|
||||
- ❌ 用 `run_python` 调 `requests` 裸打豆包 API —— 走 `seedance` tool(已封装异步轮询 + 计费 + 落盘 + meta + cancel)
|
||||
|
||||
## 输出
|
||||
|
|
|
|||
|
|
@ -102,6 +102,13 @@ class SeedanceTool(Tool):
|
|||
"type": "boolean",
|
||||
"description": "是否打豆包水印。默认 false(申报/PPT 场景反需求)。",
|
||||
},
|
||||
"generate_audio": {
|
||||
"type": "boolean",
|
||||
"description": (
|
||||
"是否同步生成 AI 背景音 / 对白(Seedance 2.0 旗舰特性)。默认 false 控成本;"
|
||||
"广告 / 短剧 / 角色对白等场景传 true,模型会一并算音轨,cost 高于纯视频。"
|
||||
),
|
||||
},
|
||||
},
|
||||
"required": ["prompt"],
|
||||
}
|
||||
|
|
@ -135,6 +142,7 @@ class SeedanceTool(Tool):
|
|||
ratio: Optional[str] = None,
|
||||
duration: Optional[int] = None,
|
||||
watermark: Optional[bool] = None,
|
||||
generate_audio: Optional[bool] = None,
|
||||
) -> str:
|
||||
if not (prompt or "").strip():
|
||||
return "[Error] prompt 不能为空"
|
||||
|
|
@ -145,6 +153,9 @@ class SeedanceTool(Tool):
|
|||
chosen_ratio = ratio or cfg.get("default_ratio", "16:9")
|
||||
chosen_duration = int(duration) if duration is not None else int(cfg.get("default_duration", 5))
|
||||
chosen_watermark = bool(cfg.get("default_watermark", False)) if watermark is None else bool(watermark)
|
||||
chosen_generate_audio = (
|
||||
bool(cfg.get("default_generate_audio", False)) if generate_audio is None else bool(generate_audio)
|
||||
)
|
||||
fps = int(cfg.get("fps", 24))
|
||||
|
||||
submit_timeout = float(cfg.get("request_timeout_s", 60))
|
||||
|
|
@ -162,6 +173,7 @@ class SeedanceTool(Tool):
|
|||
"resolution": chosen_resolution,
|
||||
"duration": chosen_duration,
|
||||
"watermark": chosen_watermark,
|
||||
"generate_audio": chosen_generate_audio,
|
||||
}
|
||||
|
||||
t0 = time.monotonic()
|
||||
|
|
@ -232,6 +244,7 @@ class SeedanceTool(Tool):
|
|||
"duration_s": chosen_duration,
|
||||
"fps": fps,
|
||||
"watermark": chosen_watermark,
|
||||
"generate_audio": chosen_generate_audio,
|
||||
"tokens": tokens_actual,
|
||||
"tokens_estimated": tokens_estimated,
|
||||
"price_cny_per_mtoken": price_t2v,
|
||||
|
|
@ -258,7 +271,11 @@ class SeedanceTool(Tool):
|
|||
price_cny_per_mtoken=price_t2v,
|
||||
has_video_input=False, # phase 1 仅 t2v;i2v 接入后这里读 body 判断
|
||||
watermark=chosen_watermark,
|
||||
extra_units={"cgt_id": cgt_id, "elapsed_s": round(elapsed, 1)},
|
||||
extra_units={
|
||||
"cgt_id": cgt_id,
|
||||
"elapsed_s": round(elapsed, 1),
|
||||
"generate_audio": chosen_generate_audio,
|
||||
},
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"[seedance] record_video_usage failed: {type(e).__name__}: {e}", flush=True)
|
||||
|
|
@ -268,7 +285,8 @@ class SeedanceTool(Tool):
|
|||
# 前端 extractMediaBanner 已 whitelist seedance,正则抓 key=value 挂徽章
|
||||
return (
|
||||
f"[seedance] model={model_id} · resolution={chosen_resolution} · ratio={chosen_ratio} · "
|
||||
f"duration={chosen_duration}s · cost=¥{cost_cny:.2f} · elapsed={elapsed:.1f}s\n"
|
||||
f"duration={chosen_duration}s · audio={chosen_generate_audio} · "
|
||||
f"cost=¥{cost_cny:.2f} · elapsed={elapsed:.1f}s\n"
|
||||
f"saved: {disp}\n"
|
||||
f"prompt={prompt!r}\n"
|
||||
f"watermark={chosen_watermark} cgt_id={cgt_id}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue