使用java实现即梦文生图 4.0,火山引擎「即梦 AI」文生图 Demo
·
一、即梦文生图能力申请
进入即梦AI:账号登录-火山引擎
进行实名认证,服务开通,获取密钥(这个是重点,后面调用功能的入口)

二、使用步骤
官方文档地址:即梦AI-图片生成4.0-接口文档--即梦AI-火山引擎
SDK方案地址:SDK使用说明--AI中台公用文档-火山引擎
java-SDK:GitHub - volcengine/volc-sdk-java · GitHub
1.引入库
获取版本地址:https://central.sonatype.com/artifact/com.volcengine/volc-sdk-java?smo=true
<dependency>
<groupId>com.volcengine</groupId>
<artifactId>volc-sdk-java</artifactId>
<version>1.0.273</version>
</dependency>
2.java代码,注意替换你AK和SK
代码如下(示例):
package cn.iocoder.yudao.module.iscs.utils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.volcengine.service.visual.IVisualService;
import com.volcengine.service.visual.impl.VisualServiceImpl;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.net.URL;
import java.util.Base64;
/**
* 火山引擎「即梦 AI」文生图 Demo。
* <p>
* 使用模型:{@code jimeng_t2i_v40}(即梦文生图 4.0)
* <p>
* 官方文档:https://www.volcengine.com/docs/85128/1554673
* <p>
* 调用流程(异步):
* <pre>
* 1. cvSync2AsyncSubmitTask — 提交文生图任务,返回 task_id
* 2. cvSync2AsyncGetResult — 按 task_id 轮询,直到 status=done
* 3. 从返回的 image_urls 或 binary_data_base64 中解析图片并保存到本地
* </pre>
* <p>
* 注意:本类为本地调试 Demo,AK/SK 硬编码仅用于测试,生产环境请改用配置中心或环境变量。
*/
public class CVProcessDemo {
/** 火山引擎 Access Key,用于 API 身份认证 */
private static final String AK = "你的AK";
/** 火山引擎 Secret Key,用于请求签名(注意 Base64 编码,末尾通常带 ==) */
private static final String SK = "你的SK";
/**
* 能力标识(req_key),指定调用的 AI 模型/能力。
* jimeng_t2i_v40 = 即梦文生图 4.0,提交与查询时均需携带同一 req_key。
*/
private static final String REQ_KEY = "jimeng_t2i_v40";
/** 轮询间隔(毫秒),即梦文生图通常需 5~30 秒,建议 3 秒查一次 */
private static final long POLL_INTERVAL_MS = 3_000;
/** 最大轮询次数,60 × 3s ≈ 3 分钟,超时则放弃 */
private static final int MAX_POLL_TIMES = 60;
/**
* 程序入口:提交文生图任务 → 轮询结果 → 保存图片。
*/
public static void main(String[] args) {
// ---------- 1. 初始化火山视觉 SDK ----------
// VisualServiceImpl 为单例,内部封装 HMAC-SHA256 签名与 HTTP 请求
IVisualService visualService = VisualServiceImpl.getInstance();
visualService.setAccessKey(AK);
visualService.setSecretKey(SK);
// 视觉智能 API 固定 endpoint,不可使用 open.volcengineapi.com
visualService.setRegion("cn-north-1");
visualService.setHost("visual.volcengineapi.com");
// ---------- 2. 构建提交任务请求体 ----------
JSONObject submitReq = new JSONObject();
submitReq.put("req_key", REQ_KEY);
// prompt:文本描述,即「画什么」;支持中文,越具体效果越好
submitReq.put("prompt", "正在打LOL的边牧,但是这局已经输了,在图片的上方加上语言气泡,显示小狗说:'队友的锅,我是svp'");
submitReq.put("width", 1024); // 输出宽度(像素),常用 1024
submitReq.put("height", 1024); // 输出高度(像素),常用 1024
try {
// ---------- 3. 提交异步任务 ----------
// 对应 API:Action=CVSync2AsyncSubmitTask, Version=2022-08-31
// 成功时返回:{ "code": 10000, "data": { "task_id": "..." } }
JSONObject submitResp = (JSONObject) visualService.cvSync2AsyncSubmitTask(submitReq);
System.out.println("提交任务返回:" + submitResp.toJSONString());
checkResponse(submitResp, "提交任务");
// 从 data 中取出 task_id,后续轮询必需
String taskId = submitResp.getJSONObject("data").getString("task_id");
if (StringUtils.isBlank(taskId)) {
System.out.println("task_id 为空,无法查询结果");
return;
}
System.out.println("task_id:" + taskId);
// ---------- 4. 轮询直到任务完成 ----------
JSONObject resultData = pollTaskResult(visualService, taskId);
if (resultData == null) {
System.out.println("任务超时或失败,未获取到图片");
return;
}
// ---------- 5. 解析并保存图片 ----------
// 使用时间戳命名,避免覆盖已有文件
long now = System.currentTimeMillis();
String outputPath = "C:\\Users\\HP\\Pictures\\Saved Pictures\\" + now + ".png";
if (saveImageFromResult(resultData, outputPath)) {
System.out.println("图片保存成功:" + new File(outputPath).getAbsolutePath());
} else {
System.out.println("未能从结果中解析图片,data 内容:" + resultData.toJSONString());
}
} catch (Exception e) {
System.err.println("调用失败: " + e.getMessage());
e.printStackTrace();
}
}
/**
* 轮询查询任务结果。
* <p>
* 对应 API:Action=CVSync2AsyncGetResult, Version=2022-08-31
* <p>
* 任务状态(data.status)常见值:
* <ul>
* <li>{@code in_queue} — 排队中,继续等待</li>
* <li>{@code generating} — 生成中,继续等待</li>
* <li>{@code done} / {@code success} — 完成,可解析图片</li>
* <li>{@code failed} / {@code error} — 失败,抛出异常</li>
* </ul>
*
* @param visualService SDK 实例
* @param taskId 提交任务时返回的任务 ID
* @return 任务完成时的 data 对象(含图片数据);超时返回 null
*/
private static JSONObject pollTaskResult(IVisualService visualService, String taskId) throws Exception {
JSONObject queryReq = new JSONObject();
queryReq.put("req_key", REQ_KEY);
queryReq.put("task_id", taskId);
for (int i = 1; i <= MAX_POLL_TIMES; i++) {
Thread.sleep(POLL_INTERVAL_MS);
JSONObject queryResp = (JSONObject) visualService.cvSync2AsyncGetResult(queryReq);
if (queryResp == null) {
System.out.println("第 " + i + " 次查询:响应为空");
continue;
}
// 响应体可能含 MB 级 Base64,超过 1000 字符时截断打印,避免控制台刷屏
String logContent = queryResp.toJSONString().length() < 1000
? queryResp.toJSONString()
: "太长不显示";
System.out.println("第 " + i + " 次查询:" + logContent);
// code=10000 为火山视觉 API 成功码;部分旧接口使用 code=0
if (queryResp.containsKey("code") && queryResp.getIntValue("code") != 10000
&& queryResp.getIntValue("code") != 0) {
throw new RuntimeException("查询失败: " + queryResp.getString("message"));
}
JSONObject data = queryResp.getJSONObject("data");
if (data == null) {
continue;
}
String status = data.getString("status");
if ("done".equalsIgnoreCase(status) || "success".equalsIgnoreCase(status)) {
return data;
}
if ("failed".equalsIgnoreCase(status) || "error".equalsIgnoreCase(status)) {
throw new RuntimeException("任务失败: " + data.toJSONString());
}
// in_queue / generating 等中间状态:不 return,进入下一轮轮询
}
return null;
}
/**
* 从任务结果 data 中解析图片并写入本地文件。
* <p>
* 火山 API 可能返回以下任一格式(按优先级依次尝试):
* <ol>
* <li>{@code image_urls} — URL 数组,下载后保存</li>
* <li>{@code image_url} — 单个 URL 字符串</li>
* <li>{@code binary_data_base64} — Base64 数组或字符串,解码后直接写文件</li>
* </ol>
*
* @param data 轮询完成后的 data 对象
* @param path 本地保存路径(含文件名)
* @return 是否成功保存
*/
private static boolean saveImageFromResult(JSONObject data, String path) throws Exception {
// 方式一:image_urls 数组(部分接口返回 CDN 临时链接,需尽快下载)
JSONArray imageUrls = data.getJSONArray("image_urls");
if (imageUrls != null && !imageUrls.isEmpty()) {
String imageUrl = imageUrls.getString(0);
if (StringUtils.isNotBlank(imageUrl)) {
System.out.println("图片地址:" + imageUrl);
saveImageFromUrl(imageUrl, path);
return true;
}
}
// 方式二:单个 image_url 字段
String imageUrl = data.getString("image_url");
if (StringUtils.isNotBlank(imageUrl)) {
System.out.println("图片地址:" + imageUrl);
saveImageFromUrl(imageUrl, path);
return true;
}
// 方式三:binary_data_base64 数组(即梦 v4 实际返回此格式)
JSONArray base64List = data.getJSONArray("binary_data_base64");
if (base64List != null && !base64List.isEmpty()) {
byte[] bytes = Base64.getDecoder().decode(base64List.getString(0));
FileUtils.writeByteArrayToFile(new File(path), bytes);
return true;
}
// 方式四:binary_data_base64 单字符串(兼容不同版本响应结构)
String base64 = data.getString("binary_data_base64");
if (StringUtils.isNotBlank(base64)) {
FileUtils.writeByteArrayToFile(new File(path), Base64.getDecoder().decode(base64));
return true;
}
return false;
}
/**
* 校验 API 响应是否成功。
*
* @param resp API 返回的 JSON 对象
* @param step 当前步骤描述(用于异常信息,如「提交任务」)
* @throws RuntimeException 响应为空、code 非成功、或 data 缺失时抛出
*/
private static void checkResponse(JSONObject resp, String step) {
if (resp == null) {
throw new RuntimeException(step + "响应为空");
}
// 火山视觉 API:code=10000 表示成功;部分旧接口 code=0
int code = resp.getIntValue("code");
if (code != 10000 && code != 0) {
throw new RuntimeException(step + "失败: " + resp.getString("message"));
}
if (resp.getJSONObject("data") == null) {
throw new RuntimeException(step + " data 字段为空");
}
}
/**
* 从 URL 下载图片并保存到本地。
*
* @param url 图片地址(通常为火山 CDN 临时链接)
* @param path 本地保存路径
*/
public static void saveImageFromUrl(String url, String path) throws Exception {
// 连接超时 10s,读取超时 60s(大图下载可能较慢)
FileUtils.copyURLToFile(new URL(url), new File(path), 10_000, 60_000);
}
}
注意:图片生成是异步的,需要时间,所以需要轮询检查任务完成情况,然后输出,注意修改文件输出。
三、验证结果


AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)