本文件是 skill-mv 唯一真实可用的生成通道的完整参考。 来源:
kb-raw/07-即梦API工具箱/(脚本 +参考文档/即梦AI技能汇总.md+参考文档/README_v2.md), 并已在 2026-10-13 于本容器实测复核(见out/verify-*.log)。 代码实现:lib/jimeng.mjs(底层)+lib/providers.mjs的jimengprovider。
技能仓原先的两条生成通道都不可用:
| 原通道 | 端点 | 实测结果 |
|---|---|---|
| AI 音乐 | /suno/submit/music |
503 Task request failed(渠道未开通) |
| 图生视频 | /v1/video/generations |
503 No available channel for model doubao-seedance-1-0-pro |
| 唇形驱动 | — | 网关无此路由(返回前端兜底页) |
| TTS | /v1/audio/speech |
网关无此路由 |
即梦通道(https://server.fmode.cn/api/volcengine/jimeng)全部实测可用,并且一次覆盖四个缺口:
文生图、图生图、图生视频、数字人/动作模仿(后两者直接替代了唇形驱动)。
任何即梦生成任务都走同样的三步。记住它,就掌握了全部 20 个端点。
POST https://server.fmode.cn/api/volcengine/jimeng/<endpoint>
Content-Type: application/json
{ "...业务参数": "...", "token": "Bearer <sessionToken>" }
成功响应:
{ "code": 200, "data": { "workId": "5mn57IrZRg" } }
POST https://server.fmode.cn/api/volcengine/jimeng/getDataByTask02
Content-Type: application/json
{ "workId": "5mn57IrZRg", "routerName": "getImgV4", "token": "Bearer <sessionToken>" }
响应:
{ "code": 200, "data": { "tip": "生成成功", "isFinish": true } }
生成中:
{ "code": 200, "data": { "tip": "生成中,请等待...", "isFinish": false } }
数字人例外:查询走
/getOhDateByTask(不是getDataByTask02), 且步骤①主体识别用isContinue而非isFinish表示「可进下一步」。
GET https://server.fmode.cn/parse/classes/ImagineWork/{workId}
X-Parse-Application-Id: ncloudmaster
响应(只列关键字段):
{
"objectId": "5mn57IrZRg",
"images": ["https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/aigc/imagine/5mn57IrZRg-0.png"],
"videos": null,
"usage": { "cost": 0.2, "credit": 2 },
"credit": 2,
"provider": "volcengine"
}
images[];视频任务 → videos[]。wget(无需鉴权头)。usage.cost 是实扣金额(元),credit 是平台积分(1 credit = ¥0.1)。
→ 本技能的费用台账优先采信 usage.cost,而不是预估。| 端点 key | path | 费用 | 单位 | 说明 |
|---|---|---|---|---|
text2imgV3 |
/getText2ImgV3 |
¥0.20 | 张 | 文生图3.0 |
text2imgV31 |
/getText2ImgV31 |
¥0.20 | 张 | 文生图3.1(美感更强) |
imgV4 |
/getImgV4 |
¥0.22 | 张 | 图片生成4.0(文生图 / 多图组合) |
img2imgV3 |
/getImg2ImgV3 |
¥0.20 | 张 | 图生图3.0 智能参考 |
imgV4Goods |
/getImgV4_goods |
¥0.22 | 张 | 商品提取 |
imgV4Pod |
/getImgV4_pod |
¥0.22 | 张 | 素材提取 |
clothesV2 |
/getClothesV2 |
¥0.22 | 张 | 虚拟换装v2 |
inpaint |
/getInpaint |
¥0.20 | 张 | 局部重绘 / 消除笔 |
superRes |
/getSuperResolution |
¥0.40 | 张 | 智能超清 |
actor |
/getActor |
¥0.50 | 秒 | 动作模仿1.0(单条 ¥4~6,最低 ¥4) |
actorV2 |
/getActorV2 |
¥0.40 | 秒 | 动作模仿2.0(单条 ¥3.2~5,最低 ¥3.2) |
video720 |
/getVideoV3_720p |
¥0.28 | 秒 | 图生视频3.0 720p(主力) |
video1080 |
/getVideoV3_1080p |
¥0.63 | 秒 | 图生视频3.0 1080p |
videoPro |
/getVideoV3_Pro |
¥1.00 | 秒 | 图生视频3.0 Pro(多镜头叙事) |
ohIdentify |
/getOhIdentifyMain |
免费 | 次 | 数字人·主体识别 |
ohDetect |
/getOhDetectMain |
免费 | 次 | 数字人·主体检测(可选) |
omniHuman |
/getOmniHuman |
¥1.00 | 秒 | 数字人·视频生成 |
费用表与 KB
即梦AI技能汇总.md一致,usage.cost已实测校验。
所有请求 body 必须带 token,格式 "Bearer <sessionToken>"。
缺失时返回 HTTP 403:
{ "error": { "message": "请输入API_KEY或用户sessionToken" } }
sessionToken 的取法(运行时读取,绝不硬编码):
// lib/jimeng.mjs
const sess = process.env.FMODE_SESSION_TOKEN
|| JSON.parse(fs.readFileSync('/opt/data/fmode-identity.json', 'utf8')).session_token;
const TOKEN = 'Bearer ' + sess;
⚠️ KB 里的原始脚本把 token 硬编码成了
Bearer r:f03...。 本技能仓一律改为运行时读取,任何文件、日志、产物里都不出现明文 token。
| 端点 | 面积约束 | 宽高比 | 推荐尺寸 |
|---|---|---|---|
text2imgV3 / text2imgV31 / img2imgV3 |
[512², 2048²] |
[1/3, 3] |
1K:1664×936(16:9)、1328×1328(1:1)、1472×1104(4:3);2K:2560×1440、2048×2048、2304×1728 |
imgV4 / imgV4_goods / imgV4_pod |
[1024², 4096²] |
[1/3, 3] |
2K:2560×1440(16:9)、2048×2048(1:1)、2304×1728(4:3);4K:5404×3040(16:9)、4096×4096 |
实测踩坑(本次修复):给
getImgV4传1280×720(面积 921,600 < 1,048,576)时, 提交阶段返回 200 + workId,轮询 15 秒后才报错:> {"algo_code":100199,"algo_msg":"run comfyui pipeline error: > nodeid:[155], node_type:[BADataProcessingTransform], message: height or width invalid "} > ``` > 因此 `lib/jimeng.mjs` 的 `assertValidSize()` 会在**本地**先卡住,避免白等一轮。 > 用 `resolveSize(endpoint, aspect, tier)` 取推荐尺寸。 ### 5.2 视频 frames —— 必须 ≡ 1 (mod 24)jsonc { "prompt": "…", // ≤400 字(建议),最长 800 字 "frames": 121, // ★ 范围 [121, 241],且 frames % 24 === 1 "method": "2", // '2'=首帧 '3'=首尾帧 "config": { "image_urls": [ "https://…/first.png" ] } // method=3 时传 [首, 尾] 两张 }
> **实测踩坑(本次修复)**:`frames=122` 被拒 > `x2v pipeline: frames % 24 should be 1`;`frames=49` 被拒 `frames 取值范围为[121,241]`。 > 合法值只有 **121 / 145 / 169 / 193 / 217 / 241**,对应 **5 / 6 / 7 / 8 / 9 / 10 秒**。 > 也就是说:**图生视频单镜只能是 5~10 秒的整数秒**,不存在 3 秒或 13 秒的镜头。 ### 5.3 首帧图片要求 - 图片长边与短边比例必须在 **3 以内**(即 `max(w,h)/min(w,h) ≤ 3`)。 - `method=3`(首尾帧)的**尾帧必须与首帧同比例**。 - 输出视频的**画幅跟随输入图**,不跟随 `sizeDate`。 ### 5.4 参考图数量 `getImgV4` 的 `image_urls` 支持 **0~10 张**,因此可以一次塞多张参考: - **人物资产流程**:`[上一步的成品图]` 1 张 - **场景 + 人物关键帧**:`[场景图, 人物多视图]` 2 张(本技能 `scene` 工序的做法) - **`scale`**:文本影响程度 `[0,1]`,默认 0.5。要在保留参考图特征的同时较多体现 prompt,用 0.5~0.7。 --- ## 六、图片预处理与公网化(图生图/图生视频的必经步骤) 即梦只吃**公网 URL**,不吃本地文件。所以任何本地图都要先上传七牛。 ### 6.1 压缩(避免体积超限) KB 的踩坑记录:即梦二进制输入限制约 **4~5MB**(base64 字符串),大 PNG 直传报 `Image Decode Error: invalid binary data file size`。js // 本技能的实现:lib/jimeng.mjs 的 prepareImageUrl() // 原图 ≤3MB 直接上传;否则 ffmpeg 压到 1280×720 JPEG q4(≈150~300KB) ffmpeg -y -v error -i in.png \ -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" \ -q:v 4 out.jpg
> 经验值:`2560×1440 PNG (~5.6MB)` → `1280×720 JPEG (~200KB)`,base64 从 ~750 万字符降到 ~28 万字符。 ### 6.2 上传七牛(拿公网直链)① POST https://server.fmode.cn/parse/functions/qiniu_uptoken headers: X-Parse-Application-Id: ncloudmaster body: { "company": "XlTE6uWQEQ" } → { "result": { "uptoken": "...", "domain": "https://file-cloud.fmode.cn/",
"zoneUrl": "https://upload-z2.qiniup.com/", "max_file_size": 400 } }
② POST {zoneUrl} (multipart/form-data) fields: token={uptoken}, key={key}, file={二进制} → { "hash": "...", "key": "storage/company/XlTE6uWQEQ/20261013/…-photo.jpg" }
③ 公网直链 = {domain} + {key} = https://file-cloud.fmode.cn/storage/company/XlTE6uWQEQ/20261013/…-photo.jpg
`key` 命名规则(照抄 KB):`storage/company/{cid}/{yyyymmdd}/{hhmmss}-{rand6}-{filename}`
> **注意**:`company` 必须是**真实存在的公司 ID**,传错会返回
> `{"code":141,"error":"Object not found."}`。
> 本仓默认用 KB 里的 `XlTE6uWQEQ`(实测可用),可用 `FMODE_CDN_COMPANY` 覆盖。
---
## 七、数字人 v1.5 完整流程
① getOhIdentifyMain body: { image_url } → workId 轮询 /getOhDateByTask { workId, routerName:'getOhIdentifyMain' } 注意:成功标志是 data.isContinue,不是 isFinish
② getOhDetectMain body: { workId } (可选,返回 mask 图)
③ getOmniHuman body: { workId, audio_url, prompt?, pe_fast_mode:true } 轮询 /getOhDateByTask { workId, routerName:'getOmniHuman' } → ImagineWork.videos[0]
- 图片与音频都要先上传公网。
- 费用 ¥1/秒。
- **并发限制**:并发过高返回 `error.message.errmsg.status === 50430`,
需退避重试(KB 的做法:`10000 * (retry + 1)` 毫秒,最多 5 次)。
---
## 八、错误码与陷阱速查
| 现象 | 原因 | 处理 |
|---|---|---|
| HTTP 403 `请输入API_KEY或用户sessionToken` | token 缺失/失效 | 检查 `FMODE_SESSION_TOKEN` |
| 提交 200 但轮询报 `height or width invalid` | `getImgV4` 面积 < 1024² | 用 `resolveSize('imgV4', …)` |
| `frames % 24 should be 1` | frames 非法 | 只用 121/145/169/193/217/241 |
| `frames 取值范围为[121,241]` | 想生成 <5s 或 >10s | 单镜固定 5~10 秒 |
| `Object not found.` (HTTP 500) | workId 不存在 | 核对 workId;探活用这个报错判断鉴权 OK |
| `50430` / `Concurrent Limit` | 并发限制 | 退避重试;批量任务之间 sleep |
| 轮询返回 `<!DOCTYPE html>` | 服务端错误 | 不解析,等下一轮重试 |
| `isFinish=true` 但 `videos` 为空 | 偶发 | 再查一次 `ImagineWork` 记录 |
| `Image Decode Error: invalid binary data file size` | 参考图/首帧图过大 | 先压缩到 ≤3MB |
| URL 返回带引号 | 偶发 | 下载前 `url.trim().replace(/^["']|["']$/g, '')` |
---
## 九、命令行速查(本技能封装)
bash fmode-mv jimeng --status # 通道状态(不花钱) fmode-mv jimeng --endpoints # 端点 + 费用表 fmode-mv jimeng --work # 查已有任务的产物直链 fmode-mv jimeng --test # 真跑一张最小文生图(¥0.20)
fmode-mv jimeng text2img --prompt "..." --width 1024 --height 1024 fmode-mv jimeng img2img --prompt "..." --ref a.png --ref b.png --scale 0.6 fmode-mv jimeng img2video --first a.png --last b.png --prompt "..." --seconds 5 fmode-mv jimeng upscale --ref a.png --resolution 4k fmode-mv jimeng actor --ref a.png --video-url "https://….mp4" fmode-mv jimeng digital-human --ref a.png --audio a.mp3 --prompt "固定机位,自然微动" fmode-mv jimeng upload --ref a.png # 只上传拿直链 ```
所有调用都会先打印预估费用,跑完打印实扣/耗时/产物路径与字节数。
| 文件 | 职责 |
|---|---|
lib/jimeng.mjs |
三段式调用、尺寸/帧数本地校验、七牛上传、数字人流程、费用台账 |
lib/providers.mjs → jimeng |
统一接口:text2img / img2img / img2video / actor / digitalHuman / upscale |
scripts/jimeng.mjs |
CLI 直调 |
scripts/character-sheet.mjs |
人物资产四步流水线(用 text2img + img2img) |
scripts/scene.mjs |
场景图(text2img)+ 关键帧(img2img 多图参考) |
scripts/video.mjs |
图生视频(img2video,含 method=3 → method=2 降级) |