火山引擎 Seedream 通用3.0 模型集成开发完整教程
- 环境变量配置
- Exec 环境隔离问题与解决方案
- API 调用示例代码
- 人像保持功能使用方法
- 常见问题与解决方案
在开始之前,你需要获取火山引擎的 Access Key:
- 登录 火山引擎控制台
- 进入 IAM → 密钥管理
- 创建或查看你的 Access Key
- 记录下
Access Key ID和Access Key Secret
有两种配置方式:临时环境变量和持久化环境文件。
方式一:临时环境变量(适用于测试)
# 在当前终端会话中设置(关闭终端后失效) export VOLCENGINE_AK="your-access-key-id" export VOLCENGINE_SK="your-access-key-secret"
方式二:环境文件(推荐,适用于生产环境)
创建环境文件 ~/.openclaw/workspace/.env.volcengine:
VOLCENGINE_AK=your-access-key-id VOLCENGINE_SK=your-access-key-secret
为什么要使用环境文件? 这涉及到 OpenClaw 的 exec 工具环境隔离问题,详见下一节。
# 检查环境变量是否设置成功 echo $VOLCENGINE_AK echo $VOLCENGINE_SK # 或者测试调用即梦 API python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "测试图片" --width 512 --height 512
在 OpenClaw 中使用 exec 工具执行命令时,环境变量不会自动继承。这是一个常见的问题:
# 在终端中设置了环境变量 export VOLCENGINE_AK="your-key" # 但是通过 exec 执行的命令无法访问这些变量! # exec 会创建一个新的进程环境,默认不继承 shell 的环境变量
# 错误示例:在 exec 中直接调用脚本 import os # 这个脚本在 exec 环境中运行时,会找不到 VOLCENGINE_AK ak = os.environ.get("VOLCENGINE_AK") # 返回 None!
**实践是使用环境文件(.env 文件)来存储凭证,然后在代码中同时支持环境变量和环境文件:
实现代码
import os def get_credentials(): """从环境变量或环境文件获取凭证""" # 优先从环境变量读取 ak = os.environ.get("VOLCENGINE_AK") sk = os.environ.get("VOLCENGINE_SK") # 如果环境变量不存在,尝试从环境文件读取 if not ak or not sk: env_file = os.path.expanduser("~/.openclaw/workspace/.env.volcengine") if os.path.exists(env_file): with open(env_file, "r") as f: for line in f: line = line.strip() if line.startswith("VOLCENGINE_AK="): ak = line.split("=", 1)[1] elif line.startswith("VOLCENGINE_SK="): sk = line.split("=", 1)[1] if not ak or not sk: raise ValueError("请设置环境变量或配置环境文件") return ak, sk
环境文件格式
# ~/.openclaw/workspace/.env.volcengine # 格式:KEY=VALUE,每行一个变量 VOLCENGINE_AK=AKLTXXXXXXNDUxNDkxZTg3YjUw VOLCENGINE_SK=TkdWXXXXXXV1V5WmpobE5HRXdPVGxrXXXXXX
# 推荐的凭证管理方式 class VolcEngineCredentials: """火山引擎凭证管理""" ENV_FILE = "~/.openclaw/workspace/.env.volcengine" @classmethod def get(cls): """获取凭证,优先环境变量,其次环境文件""" ak = os.environ.get("VOLCENGINE_AK") sk = os.environ.get("VOLCENGINE_SK") if not ak or not sk: cls._load_from_file() ak = os.environ.get("VOLCENGINE_AK") sk = os.environ.get("VOLCENGINE_SK") if not ak or not sk: raise ValueError( "未找到凭证!请设置环境变量 VOLCENGINE_AK 和 VOLCENGINE_SK, " "或创建环境文件: ~/.openclaw/workspace/.env.volcengine" ) return ak, sk @classmethod def _load_from_file(cls): """从环境文件加载凭证""" env_path = os.path.expanduser(cls.ENV_FILE) if not os.path.exists(env_path): return with open(env_path, "r") as f: for line in f: line = line.strip() if "=" in line and not line.startswith("#"): key, value = line.split("=", 1) os.environ[key] = value
即梦 AI 使用火山引擎的 Seedream 通用3.0 模型,API 调用分为两步:
- 提交任务:调用
CVSync2AsyncSubmitTask提交文生图请求 - 查询结果:调用
CVSync2AsyncGetResult轮询任务状态
完整示例代码
#!/usr/bin/env python3 """即梦 AI 文生图 - 完整示例""" import os import json import time import hashlib import hmac import urllib.request import urllib.parse from datetime import datetime # API 配置 SERVICE = "cv" VERSION = "2022-08-31" REGION = "cn-north-1" HOST = "visual.volcengineapi.com" REQ_KEY = "high_aes_general_v30l_zt2i" def get_credentials(): """获取凭证""" ak = os.environ.get("VOLCENGINE_AK") sk = os.environ.get("VOLCENGINE_SK") if not ak or not sk: env_file = os.path.expanduser("~/.openclaw/workspace/.env.volcengine") if os.path.exists(env_file): with open(env_file, "r") as f: for line in f: line = line.strip() if line.startswith("VOLCENGINE_AK="): ak = line.split("=", 1)[1] elif line.startswith("VOLCENGINE_SK="): sk = line.split("=", 1)[1] return ak, sk def sign_request(ak, sk, method, path, query, body=""): """生成火山引擎签名 V4""" now = datetime.utcnow() x_date = now.strftime("%Y%m%dT%H%M%SZ") short_date = now.strftime("%Y%m%d") body_hash = hashlib.sha256(body.encode()).hexdigest() canonical_headers = f"content-type:application/json host:{HOST} x-content-sha256:{body_hash} x-date:{x_date} " signed_headers = "content-type;host;x-content-sha256;x-date" sorted_query = sorted(query.items()) canonical_query = "&".join([f"{k}={urllib.parse.quote(str(v), safe='')}" for k, v in sorted_query]) canonical_request = f"{method} {path} {canonical_query} {canonical_headers} {signed_headers} {body_hash}" credential_scope = f"{short_date}/{REGION}/{SERVICE}/request" string_to_sign = f"HMAC-SHA256 {x_date} {credential_scope} {hashlib.sha256(canonical_request.encode()).hexdigest()}" k_date = hmac.new(sk.encode(), short_date.encode(), hashlib.sha256).digest() k_region = hmac.new(k_date, REGION.encode(), hashlib.sha256).digest() k_service = hmac.new(k_region, SERVICE.encode(), hashlib.sha256).digest() k_signing = hmac.new(k_service, "request".encode(), hashlib.sha256).digest() signature = hmac.new(k_signing, string_to_sign.encode(), hashlib.sha256).hexdigest() authorization = f"HMAC-SHA256 Credential={ak}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}" return { "Authorization": authorization, "X-Date": x_date, "X-Content-Sha256": body_hash, "Content-Type": "application/json", "Host": HOST } def make_request(ak, sk, action, body_params): """发送 API 请求""" query = {"Action": action, "Version": VERSION} body = json.dumps(body_params) headers = sign_request(ak, sk, "POST", "/", query, body) url = f" {HOST}/?{urllib.parse.urlencode(query)}" req = urllib.request.Request(url, data=body.encode(), headers=headers, method="POST") with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode()) def submit_task(ak, sk, prompt, width=1328, height=1328): """提交文生图任务""" body = { "req_key": REQ_KEY, "prompt": prompt, "width": width, "height": height, "seed": -1, "use_pre_llm": False, "scale": 2.5 } return make_request(ak, sk, "CVSync2AsyncSubmitTask", body) def query_task(ak, sk, task_id): """查询任务状态""" body = { "req_key": REQ_KEY, "task_id": task_id, "req_json": json.dumps({"return_url": True, "logo_info": {"add_logo": False}}) } return make_request(ak, sk, "CVSync2AsyncGetResult", body) def generate_image(prompt, width=1328, height=1328, timeout=120): """生成图片""" ak, sk = get_credentials() # 1. 提交任务 result = submit_task(ak, sk, prompt, width, height) if result.get("code") != 10000: print(f"提交失败: {result}") return None task_id = result["data"]["task_id"] print(f"任务已提交: {task_id}") # 2. 轮询结果 start_time = time.time() while time.time() - start_time < timeout: time.sleep(3) result = query_task(ak, sk, task_id) status = result.get("data", {}).get("status") if status == "done": return result["data"]["image_urls"] print(f"状态: {status}, 等待中...") print("任务超时") return None # 使用示例 if __name__ == "__main__": urls = generate_image("一只戴墨镜的柴犬,电影海报风格") if urls: print(f"生成成功: {urls[0]}")
即梦 AI 提供了便捷的命令行工具:
# 基础用法 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "你的提示词" # 指定尺寸 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "东方风格楼阁夜景,灯火通明" --width 1664 --height 936 # 指定输出目录 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "群玉阁夜景" --output ./output/images # 异步模式(不等待完成) python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "夕阳下的古建筑" --no-wait # 开启文本扩写(增强提示词) python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py "猫" --use-pre-llm
prompt string 必填 文本描述
--width int 1328 图片宽度 (512-2048)
--height int 1328 图片高度 (512-2048)
--seed int -1 随机种子 (-1为随机)
--scale float 2.5 文本影响程度 (1-10)
--use-pre-llm bool False 开启文本扩写
--output string ./tmp 输出目录
--no-wait bool False 不等待完成
--timeout int 120 超时时间(秒)
{ "task_id": "xxx", "status": "done", "image_urls": [" ..."], "local_files": ["/path/to/seedream_xxx.jpg"] }
人像保持(Portrait Consistency)是即梦 AI 的高级功能,可以:
- 基于一张形象图保持人脸特征
- 通过 prompt 定义穿搭、场景、姿势
- 支持风格迁移,学习其他图片的风格
适用场景:
- AI 虚拟形象生成
- 个人头像定制
- 虚拟人物换装
# 基础调用 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_avatar.py /path/to/face.jpg --prompt "身穿古装,站在楼阁中" # 指定尺寸 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_avatar.py /path/to/face.jpg --prompt "现代都市风格,穿西装" --width 1000 --height 1000 # 学习形象图风格(包括姿势、发色、画风) python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_avatar.py /path/to/face.jpg --prompt "穿红色礼服" --facestyle # 使用风格图迁移风格 python3 ~/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_avatar.py /path/to/face.jpg --prompt "穿汉服" --style-image /path/to/style.jpg
face_image string 必填 形象图路径
--prompt string "" 文本提示词
--style-image string None 风格图路径
--width int 1000 图片宽度 (600-1500)
--height int 1000 图片高度 (600-1500)
--seed int -1 随机种子
--step int 18 采样步数
--cfg float 6.0 CFG 值
--clarity float 0.6 清晰度 (0-1)
--no-face-v2 bool False 不使用人脸学习v2
--facestyle bool False 学习形象图风格
--output string ./tmp 输出目录
人脸学习 v2 (face_v2_switch)
- 推荐开启(默认开启)
- 更准确地保持人脸特征
- 适合真人照片转动漫风格
学习形象图风格 (facestyle_switch)
- 学习形象图的姿势、发色、画风
- 适合保持整体形象一致性
- 注意:可能影响人脸相似度
风格迁移 (style_switch)
- 学习风格图的艺术风格
- 不改变人脸特征
- 适合快速风格变化
#!/usr/bin/env python3 """人像保持功能 - 完整示例""" import os import json import base64 import urllib.request from datetime import datetime def generate_avatar_with_consistency( face_image_path, prompt="", style_image_path=None, use_face_v2=True, use_facestyle=False, width=1000, height=1000 ): """生成保持人像特征的图片""" # 1. 获取凭证 ak, sk = get_credentials() # 2. 读取形象图并转换为 base64 with open(face_image_path, "rb") as f: face_image_base64 = base64.b64encode(f.read()).decode() # 3. 构建请求参数 body = { "req_key": "img2img_anime_accelerated_maintain_id_for_smart_drawing_anime", "positive_prompt": f"best_quality,anime_style,{prompt}" if prompt else "best_quality,anime_style", "binary_data_base64": [face_image_base64], "width": width, "height": height, "face_image": "uri://binary_data?index=0", "face_detection_switch": True, "face_switch": True, # 开启人脸学习 "face_v2_switch": use_face_v2, # 使用v2版本 "facestyle_switch": use_facestyle, # 学习形象图风格 "pose_switch": True, "logo_info": {"add_logo": False} } # 4. 如果有风格图 if style_image_path: with open(style_image_path, "rb") as f: style_image_base64 = base64.b64encode(f.read()).decode() body["binary_data_base64"].append(style_image_base64) body["style_image"] = "uri://binary_data?index=1" body["style_switch"] = True # 5. 发送请求(同步API) result = make_request(ak, sk, "CVProcess", body) if result.get("code") == 10000: return result["data"]["image_urls"][0] else: print(f"生成失败: {result}") return None # 使用示例 if __name__ == "__main__": # 基础用法:只保持人脸 url = generate_avatar_with_consistency( face_image_path="/path/to/face.jpg", prompt="身穿古装,站在楼阁中,优雅姿态" ) # 学习形象图风格 url = generate_avatar_with_consistency( face_image_path="/path/to/face.jpg", prompt="穿红色礼服", use_facestyle=True ) # 风格迁移 url = generate_avatar_with_consistency( face_image_path="/path/to/face.jpg", prompt="穿汉服", style_image_path="/path/to/style.jpg" ) print(f"生成成功: {url}")
- 形象图选择:
- 清晰的正面或半侧面照片
- 光线均匀,五官清晰
- 背景简洁为佳
- Prompt 编写:
- 描述穿搭、场景、姿势
- 不要描述人脸特征(会自动保持)
- 可以添加风格关键词:
anime_style,best_quality
- 参数调优:
- 清晰度
clarity:0.5-0.7 适合大多数场景 - CFG 值:5.0-7.0 效果较好
- 步数
step:18 为默认,更高步数细节更丰富
- 清晰度
Q: 提示"请设置环境变量 VOLCENGINE_AK 和 VOLCENGINE_SK"
原因:未配置凭证或环境文件不存在
解决方案:
# 方法1:临时设置环境变量 export VOLCENGINE_AK="your-access-key-id" export VOLCENGINE_SK="your-access-key-secret" # 方法2:创建环境文件(推荐) cat > ~/.openclaw/workspace/.env.volcengine << EOF VOLCENGINE_AK=your-access-key-id VOLCENGINE_SK=your-access-key-secret EOF
Q: 在 exec 中执行脚本时找不到环境变量
原因:exec 环境隔离,默认不继承 shell 环境变量
解决方案:使用环境文件方式(见第2节),代码会自动从文件读取
Q: 任务提交失败,返回 code 非 10000
常见错误码:
调试方法:
result = submit_task(ak, sk, prompt) print(f”完整响应: {json.dumps(result, indent=2)}“)
Q: 任务一直处于 IN_QUEUE 状态
原因:服务繁忙或并发限制
解决方案:
- 免费额度只有 1 个并发,需排队等待
- 增加超时时间:
–timeout 300 - 检查是否有其他任务在运行
Q: 图片 URL 有效期多长?
答案:24小时
解决方案:生成后立即下载保存到本地
import urllib.request
def download_image(url, output_path):
urllib.request.urlretrieve(url, output_path)
Q: 生成的图片人脸不像本人
原因和解决方案:
- 形象图质量问题
- 使用正面清晰照片
- 避免侧脸或遮挡
- facestyle_switch 冲突
- 关闭
–facestyle选项 - 或者使用更高质量的参考图
- 关闭
- prompt 描述冲突
- 不要在 prompt 中描述人脸特征
- 只描述穿搭、场景、姿势
Q: 生成的图片风格不对
解决方案:
- 使用风格图:
–style-image /path/to/style.jpg - 在 prompt 中明确风格:
anime_style,oil_painting_style - 调整
–cfg值(越高越遵循 prompt)
Q: 图片尺寸支持范围
文生图:512-2048,推荐 1328x1328
人像保持:600-1500,推荐 1000x1000
Q: 免费额度是多少?
- 免费额度:500 次
- 并发限制:免费 1 并发,付费 2 并发
- 单次调用:0.2 元
Q: 如何查看剩余额度?
登录 火山引擎视觉智能控制台 查看
Q: 如何提高生成速度?
- 使用异步模式
# 提交后不等待,后续手动查询 python3 jimeng_image.py “prompt” –no-wait
- 减小图片尺寸
python3 jimeng_image.py “prompt” –width 1024 –height 1024
- 减少采样步数(人像保持)
python3 jimeng_avatar.py face.jpg –step 15
Q: 批量生成时如何避免并发限制?
解决方案:串行执行,每次生成后等待完成
import time
prompts = [“提示词1”, “提示词2”, “提示词3”] for prompt in prompts:
generate_image(prompt) time.sleep(1) # 避免频繁请求
~/.openclaw/workspace/skills/jimeng-skills/ ├── SKILL.md # 技能说明文档 ├── scripts/ │ ├── jimeng_image.py # 文生图脚本 │ ├── jimeng_avatar.py # 人像保持脚本 │ └── jimeng_v40.py # V4.0 版本脚本 └── references/ └── api_docs.md # API 文档参考
- 火山引擎控制台
- 视觉智能控制台
- Seedream 通用3.0 文档
- 人像保持模型文档
完整示例代码位于:
- 文生图:
/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_image.py - 人像保持:
/.openclaw/workspace/skills/jimeng-skills/scripts/jimeng_avatar.py
本教程详细介绍了即梦 AI 文生图的集成方法:
- 环境配置:使用环境文件解决 exec 环境隔离问题
- API 调用:完整的签名认证和异步任务处理
- 人像保持:基于形象图的特征保持和风格迁移
- 常见问题:环境变量、API 错误、性能优化等解决方案
关键要点:
- ✅ 使用环境文件而非硬编码凭证
- ✅ 理解异步任务的两步调用流程
- ✅ 人像保持需要正面清晰的形象图
- ✅ 注意图片 URL 的 24 小时有效期
希望这篇教程能帮助你顺利集成即梦 AI 文生图功能!
文档版本:v1.0
最后更新:2025年1月
作者:凝光
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/260348.html