HappyHorse 视频生成
使用 EasyRouter 统一接口调用阿里云 HappyHorse 1.0 全系列视频生成模型,支持文生视频、图生视频、参考生视频、视频编辑四种能力。
HappyHorse(快乐马)是阿里云百炼推出的视频生成模型家族,具备画面物理真实、运动流畅的特点。EasyRouter 将上游 DashScope 的异步任务接口封装为统一的 /v1/video/generations 异步任务接口对外提供服务,覆盖文生视频、图生视频、参考生视频、视频编辑四种能力。
HappyHorse 是异步任务型接口:提交后立即返回 task_id,你需要轮询任务状态,成功后从 data.result_url 下载视频。
一、支持的模型
| 模型 | 能力 | 必传媒体输入 | 说明 |
|---|---|---|---|
happyhorse-1.0-t2v | 文生视频 | — | 纯文本描述生成视频 |
happyhorse-1.0-i2v | 图生视频 | 1 张首帧图 | 以首帧图为起点,按 prompt 生成后续动作 |
happyhorse-1.0-r2v | 参考生视频 | 1~9 张参考图 | 多图参考生成,prompt 中用 [Image N] 指代 |
happyhorse-1.0-video-edit | 视频编辑 | 1 段视频 + 0~5 张参考图 | 对视频做风格变换、局部替换等编辑 |
4 个模型统一使用同一个接口路径 /v1/video/generations,仅通过 model 字段区分能力;响应体结构完全一致。
二、通用接口
2.1 提交任务
POST /v1/video/generations请求头
| Header | 必填 | 说明 |
|---|---|---|
Authorization | ✓ | Bearer sk-你的APIKey |
Content-Type | ✓ | application/json |
请求体字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✓ | HappyHorse 模型名,见上表 |
prompt | string | ✓ | 文本提示词。不超过 5000 个非中文字符或 2500 个中文字符,超长自动截断 |
size | string | — | 分辨率档位。可选 720P / 1080P(默认 1080P) |
duration | int | — | 视频时长(秒),取值 3~15,默认 5。video-edit 忽略此字段(时长跟随输入视频,最长 15 秒) |
input_reference | string | 见模型 | i2v 专用:首帧图 URL(公网可访问) |
metadata | object | 见模型 | HappyHorse 特有参数容器,见第三节 |
响应
{
"id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"object": "video",
"model": "happyhorse-1.0-t2v",
"status": "queued",
"progress": 0,
"created_at": 1778250615
}id / task_id 是 EasyRouter 生成的公开 ID(task_ 前缀),用于后续查询。不等于上游 DashScope 的 task_id,请务必使用此处返回的值。
2.2 查询任务状态
GET /v1/video/generations/{task_id}响应采用 EasyRouter 统一的 {code, message, data} 包装格式,data 中包含任务详情、扣费信息、渠道信息及上游原始响应。
响应(排队中 / NOT_START)
{
"code": "success",
"message": "",
"data": {
"id": 23,
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"platform": "17",
"user_id": 3,
"group": "default",
"channel_id": 18,
"quota": 178500,
"action": "textGenerate",
"status": "NOT_START",
"fail_reason": "",
"submit_time": 1778250615,
"start_time": 0,
"finish_time": 0,
"created_at": 1778250615,
"updated_at": 1778250615,
"progress": "0%",
"properties": {
"input": "",
"upstream_model_name": "happyhorse-1.0-t2v",
"origin_model_name": "happyhorse-1.0-t2v"
},
"data": {
"output": {
"task_id": "89c3124e-c1eb-4017-a4db-8b81536dfd22",
"task_status": "PENDING"
},
"request_id": "85a9f836-4bbe-9b95-bbfd-f3ee1309cebb"
}
}
}响应(生成中 / IN_PROGRESS)
{
"code": "success",
"message": "",
"data": {
"id": 23,
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"status": "IN_PROGRESS",
"progress": "30%",
"submit_time": 1778250615,
"start_time": 1778250620,
"finish_time": 0,
"properties": {
"upstream_model_name": "happyhorse-1.0-t2v",
"origin_model_name": "happyhorse-1.0-t2v"
},
"data": {
"output": { "task_status": "RUNNING" }
}
}
}响应(成功 / SUCCESS)
{
"code": "success",
"message": "",
"data": {
"id": 18,
"task_id": "task_SEf9uAzULfIdexfoVEcrpuhNNmQvJVfZ",
"platform": "17",
"user_id": 3,
"group": "default",
"channel_id": 18,
"quota": 297500,
"action": "textGenerate",
"status": "SUCCESS",
"fail_reason": "",
"result_url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=...&Signature=...",
"submit_time": 1778249722,
"start_time": 1778249737,
"finish_time": 1778249834,
"created_at": 1778249722,
"updated_at": 1778249834,
"progress": "100%",
"properties": {
"input": "",
"upstream_model_name": "happyhorse-1.0-r2v",
"origin_model_name": "happyhorse-1.0-r2v"
},
"data": {
"output": {
"task_id": "54b32dcb-6887-4839-bd1b-3bf73efef38c",
"end_time": "2026-05-08 22:16:57.506",
"video_url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4",
"orig_prompt": "身着红色旗袍的女性...",
"submit_time": "2026-05-08 22:15:22.401",
"task_status": "SUCCEEDED"
},
"usage": {
"SR": 720,
"ratio": "16:9",
"duration": 5,
"video_count": 1,
"input_video_duration": 0,
"output_video_duration": 5
},
"request_id": "9f888f70-8519-90b7-a540-a69a31e03181"
}
}
}响应(失败 / FAILURE)
{
"code": "success",
"message": "",
"data": {
"id": 25,
"task_id": "task_xxx",
"status": "FAILURE",
"fail_reason": "InvalidParameter: ...",
"progress": "100%",
"data": {
"output": { "task_status": "FAILED" }
}
}
}关键字段
| 字段 | 类型 | 说明 |
|---|---|---|
code | string | 响应码,成功时为 "success" |
message | string | 响应消息 |
data.id | int | 内部任务自增 ID |
data.task_id | string | EasyRouter 公开任务 ID(以 task_ 开头) |
data.status | string | 任务状态:NOT_START / QUEUED / IN_PROGRESS / SUCCESS / FAILURE |
data.result_url | string | 视频结果 URL(仅 SUCCESS 时非空,为上游 OSS 临时签名链接) |
data.fail_reason | string | 失败原因(仅 FAILURE 时非空) |
data.quota | int | 本次任务扣费的 quota 原始值 |
data.progress | string | 进度字符串,形如 "30%" / "100%" |
data.submit_time / start_time / finish_time | int64 | 提交 / 开始 / 完成的 Unix 时间戳(秒) |
data.created_at / updated_at | int64 | 记录创建 / 最近更新时间 |
data.properties.upstream_model_name | string | 实际发给上游 DashScope 的模型名 |
data.properties.origin_model_name | string | 客户端请求的模型名 |
data.data | object | 上游 DashScope 原始响应(包含 output.video_url、usage、request_id) |
状态枚举
| 状态 | 对应 DashScope 状态 | 说明 |
|---|---|---|
NOT_START | PENDING | 已创建,尚未开始处理(提交瞬间) |
QUEUED | PENDING | 已进入上游队列 |
IN_PROGRESS | RUNNING | 生成中 |
SUCCESS | SUCCEEDED | 已完成,result_url 为视频地址 |
FAILURE | FAILED / CANCELED / UNKNOWN | 生成失败,fail_reason 为失败原因 |
视频 URL(data.result_url)是上游 OSS 签名链接,Expires= 参数一般 24 小时有效,获取后请尽快下载或转存到你自己的存储。
三、HappyHorse 特有参数(metadata)
以下字段都通过请求体的 metadata 对象传递,EasyRouter 会透传给上游 DashScope。
3.1 视频控制参数
| 字段 | 类型 | 适用模型 | 说明 | 默认值 |
|---|---|---|---|---|
ratio | string | t2v / r2v | 宽高比,可选 16:9 / 9:16 / 1:1 / 4:3 / 3:4 | 16:9 |
watermark | bool | 所有 | 是否添加水印(右下角 "Happy Horse" 字样) | true |
seed | int | 所有 | 随机种子,取值 0 ~ 2147483647,未指定自动生成 | — |
audio_setting | string | video-edit | 声音控制:auto(模型控制)/ origin(保留原视频声音) | auto |
i2v 不支持 ratio 参数:图生视频的宽高比自动跟随输入首帧图的比例。
3.2 多媒体输入(input.media)
r2v 与 video-edit 需要通过 metadata.input.media 数组传入媒体素材:
{
"metadata": {
"input": {
"media": [
{ "type": "reference_image", "url": "https://.../img1.jpg" },
{ "type": "reference_image", "url": "https://.../img2.jpg" },
{ "type": "video", "url": "https://.../video.mp4" }
]
}
}
}type | 用途 | 数量限制 |
|---|---|---|
reference_image | 参考图片(r2v 和 video-edit 都支持) | r2v: 1 |
video | 待编辑视频(仅 video-edit 使用) | video-edit: 必须且仅有 1 个 |
first_frame | 首帧图(仅 i2v 使用,也可通过顶层 input_reference 传递) | i2v: 仅 1 张 |
r2v 提示词规范:在 prompt 中通过 [Image 1]、[Image 2] 按数组顺序指代参考图,例如"[Image 1]中身着红色旗袍的女性,轻抬玉手展开[Image 2]中的折扇"。
3.3 媒体素材限制
| 类型 | 格式 | 分辨率 | 文件大小 | 其他 |
|---|---|---|---|---|
| 图片(i2v 首帧) | JPEG / JPG / PNG / WEBP | 宽高 ≥ 300 像素 | ≤ 10 MB | 宽高比 1:2.5 ~ 2.5:1 |
| 图片(r2v 参考图) | JPEG / JPG / PNG / WEBP | 短边 ≥ 400 像素(推荐 720P+) | ≤ 10 MB | 推荐清晰图,避免模糊过压 |
| 图片(video-edit 参考图) | JPEG / JPG / PNG / WEBP | 宽高 ≥ 300 像素 | ≤ 10 MB | 宽高比 1:2.5 ~ 2.5:1 |
| 视频(video-edit 输入) | MP4 / MOV(推荐 H.264) | 长边 ≤ 2160,短边 ≥ 320 | ≤ 100 MB | 3~60 秒,>8 fps,宽高比 1:2.5 ~ 2.5:1 |
video-edit 输出时长规则:输入视频 ≤15 秒时输出等同长度;输入视频 >15 秒时系统自动截取前 15 秒,因此输出最长 15 秒。
四、完整调用示例
# Step 1: 提交任务
curl -X POST https://easyrouter.io/v1/video/generations \
-H "Authorization: Bearer sk-你的APIKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-t2v",
"prompt": "一只猫在阳光下打盹,毛毛随风轻轻摇曳",
"size": "720P",
"duration": 5,
"metadata": {
"ratio": "16:9",
"seed": 42,
"watermark": false
}
}'
# 响应(OpenAI 扁平格式):
# {
# "id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
# "task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
# "status": "queued", ...
# }
# Step 2: 轮询(建议间隔 10~15 秒)
curl https://easyrouter.io/v1/video/generations/task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o \
-H "Authorization: Bearer sk-你的APIKey"
# Step 3: 当 data.status == "SUCCESS" 后,从 data.result_url 下载视频
curl -o cat.mp4 "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=..."# i2v:通过 input_reference 传入首帧图
curl -X POST https://easyrouter.io/v1/video/generations \
-H "Authorization: Bearer sk-你的APIKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-i2v",
"prompt": "镜头缓慢推近,画面生动起来",
"size": "720P",
"duration": 5,
"input_reference": "https://example.com/girl.jpg"
}'i2v 的宽高比自动跟随 input_reference 输入图像,不支持 metadata.ratio。
# r2v:最多 9 张参考图,prompt 中用 [Image 1]、[Image 2] 指代
curl -X POST https://easyrouter.io/v1/video/generations \
-H "Authorization: Bearer sk-你的APIKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-r2v",
"prompt": "[Image 1]中身着红色旗袍的女性轻抬玉手展开[Image 2]中的折扇,[Image 3]中的流苏耳坠随头部转动轻盈摆动",
"size": "720P",
"duration": 5,
"metadata": {
"ratio": "16:9",
"input": {
"media": [
{ "type": "reference_image", "url": "https://example.com/girl.jpg" },
{ "type": "reference_image", "url": "https://example.com/folding-fan.jpg" },
{ "type": "reference_image", "url": "https://example.com/earrings.jpg" }
]
}
}
}'# video-edit:1 个视频 + 最多 5 张参考图
curl -X POST https://easyrouter.io/v1/video/generations \
-H "Authorization: Bearer sk-你的APIKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-video-edit",
"prompt": "让视频中的马头人身角色穿上图片中的条纹毛衣",
"size": "720P",
"metadata": {
"audio_setting": "origin",
"input": {
"media": [
{ "type": "video", "url": "https://example.com/source.mp4" },
{ "type": "reference_image", "url": "https://example.com/sweater.webp" }
]
}
}
}'video-edit 不需要指定 duration,输出时长跟随输入视频(≤15 秒)。
五、轮询建议
| 项 | 建议 |
|---|---|
| 轮询间隔 | 10~15 秒一次,不要小于 5 秒以避免限流 |
| 终态判断 | data.status == "SUCCESS" 或 data.status == "FAILURE" |
| 总超时时间 | t2v / i2v / r2v 建议 5 分钟;video-edit 建议 8~10 分钟 |
| 典型耗时 | t2v / i2v / r2v:100 |
| 视频 URL 有效期 | 一般 24 小时,获取后请立即下载或转存 |
简易轮询脚本(Bash)
#!/bin/bash
TID="task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o"
KEY="sk-你的APIKey"
while true; do
RESP=$(curl -sS "https://easyrouter.io/v1/video/generations/$TID" -H "Authorization: Bearer $KEY")
echo "$RESP"
STATUS=$(echo "$RESP" | python3 -c "import sys,json;print(json.load(sys.stdin)['data'].get('status',''))")
case "$STATUS" in
SUCCESS|FAILURE) break ;;
esac
sleep 15
done六、错误处理
6.1 HTTP 400 参数错误(提交前拦截,不扣费)
EasyRouter 在提交到上游前会对必填字段做基础校验:
| 场景 | 响应 |
|---|---|
未传 prompt | {"code":"invalid_request","message":"prompt is required","data":null} |
| 未知模型名 | {"code":"invalid_request","message":"unknown model: ..."} |
6.2 HTTP 401 / 403 鉴权错误
401 Unauthorized:API Key 无效或已过期403 Forbidden:API Key 无权访问此模型(检查 token 的模型白名单)
6.3 HTTP 402 余额不足
返回 insufficient user quota。请前往 EasyRouter 控制台充值。
6.4 任务 FAILURE 状态
任务成功提交但上游生成失败(data.status == "FAILURE"),常见原因见 data.fail_reason:
| 原因 | 处理建议 |
|---|---|
| 内容审核失败 | 调整 prompt,避免敏感内容 |
i2v 未提供 input_reference | 图生视频必须传入首帧图 |
| r2v 参考图数量为 0 | 至少提供 1 张 reference_image |
| video-edit 未提供视频 | media 中必须包含 1 个 type: video 元素 |
| 媒体 URL 不可访问 | 确保 URL 公开可访问、未过期 |
| 媒体文件不符规格 | 参考第 3.3 节素材限制 |
| 参数组合非法(如分辨率不支持) | 按第三节规范传参 |
任务 FAILURE 时 EasyRouter 会自动退款到你的账户,可在日志页面查询退款记录。
七、OpenAI 兼容接口(可选)
除了主推的 /v1/video/generations 接口外,HappyHorse 同时兼容 OpenAI 风格的 /v1/videos 接口,便于直接接入 OpenAI SDK / 客户端。两套接口完全等价(同一个后端任务),选择哪一个由你的客户端集成方式决定。
7.1 提交(OpenAI 兼容)
POST /v1/videos请求体字段与 /v1/video/generations 完全一致。返回的也是 OpenAI 扁平格式。
7.2 查询(OpenAI 兼容)
GET /v1/videos/{task_id}返回 OpenAI 标准格式(扁平结构):
{
"id": "task_hI0pZ1xklxOsDWK2wYyK30DT3QQUjM7A",
"object": "video",
"model": "happyhorse-1.0-t2v",
"status": "completed",
"progress": 100,
"created_at": 1778249702,
"completed_at": 1778249795,
"metadata": {
"url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=...&Signature=..."
}
}OpenAI 状态枚举映射
| OpenAI 状态 | 对应统一格式状态 |
|---|---|
queued | NOT_START / QUEUED |
in_progress | IN_PROGRESS |
completed | SUCCESS |
failed | FAILURE |
提交和查询可以混用不同接口:例如用 POST /v1/video/generations 提交,用 GET /v1/videos/{id} 查询也完全可以,两者使用的是同一个 task_id。但建议在同一业务流程中保持一致,便于排查问题。