diff --git a/README.md b/README.md index 38cdf8f..7c60d22 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,20 @@ ## ⚙️ 设置:配置 API 密钥 +### 方式 1:手动配置 + 1. 在插件根目录中找到 `api_keys.json.example` 文件。 2. 将其**重命名**为 `api_keys.json`。 3. 打开文件并填入您的密钥信息([从此获取 Key](https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey))。 +### 方式 2:节点内配置 + +1. 在 ComfyUI 中添加 **Jimeng API Client** 节点。 +2. 在 `key_name` 下拉框中选择 **Custom**。 +3. 在弹出的输入框中填入您的 API Key。 +4. (可选)在 `new_key_name` 中填入一个名称(如 "MyKey"),运行一次后该 Key 将被自动保存。 + * *注意:保存后需刷新浏览器页面,新密钥才会显示在下拉列表中。* + ## 📖 功能节点列表 (所有节点均位于 `JimengAI` 菜单下) @@ -59,7 +69,7 @@ - **特性**: 支持自定义尺寸,支持引导系数调节。 **示例工作流**: -![Seedream 3 Workflow](example_workflows/Seedream%203.png) +![Seedream 3 Workflow](example_workflows/Seedream%203.jpg) --- @@ -69,7 +79,7 @@ - **输入图像**: 支持单张或多张(Batch)图像作为参考。 **示例工作流**: -![Seedream 4 Workflow](example_workflows/Seedream%204.png) +![Seedream 4 Workflow](example_workflows/Seedream%204.jpg) --- @@ -84,7 +94,7 @@ 支持按状态、模型版本或任务 ID 过滤查询任务历史。 **示例工作流**: -![Seedance Workflow](example_workflows/Seedance.png) +![Seedance 1 Workflow](example_workflows/Seedance%201.jpg) ## 📓 示例工作流 diff --git a/example_workflows/Seedance 1.jpg b/example_workflows/Seedance 1.jpg new file mode 100644 index 0000000..1577ef3 Binary files /dev/null and b/example_workflows/Seedance 1.jpg differ diff --git a/example_workflows/Seedance 1.json b/example_workflows/Seedance 1.json new file mode 100644 index 0000000..0a86aed --- /dev/null +++ b/example_workflows/Seedance 1.json @@ -0,0 +1 @@ +{"id":"c6030a59-7432-4d9e-9c27-3a4587d93b75","revision":0,"last_node_id":28,"last_link_id":37,"nodes":[{"id":10,"type":"ShowText|pysssss","pos":[1220.254936410543,1035.1893951354434],"size":[140,26],"flags":{},"order":8,"mode":4,"inputs":[{"label":"文本","localized_name":"文本","name":"text","type":"STRING","link":9}],"outputs":[{"label":"字符串","localized_name":"字符串","name":"STRING","shape":6,"type":"STRING","links":null}],"title":"展示文本","properties":{"cnr_id":"comfyui-custom-scripts","ver":"f2838ed5e59de4d73cde5c98354b87a8d3200190","Node name for S&R":"ShowText|pysssss"},"widgets_values":[]},{"id":7,"type":"SaveVideo","pos":[623.132267622935,1035.1893951354434],"size":[270,106],"flags":{},"order":9,"mode":4,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":32},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":8,"type":"JimengVideoQueryTasks","pos":[934.7428721646523,1035.1893951354434],"size":[270,246],"flags":{},"order":4,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":7},{"localized_name":"页码","name":"page_num","type":"INT","widget":{"name":"page_num"},"link":null},{"localized_name":"每页数量","name":"page_size","type":"INT","widget":{"name":"page_size"},"link":null},{"localized_name":"任务状态","name":"status","type":"COMBO","widget":{"name":"status"},"link":null},{"localized_name":"服务等级","name":"service_tier","type":"COMBO","widget":{"name":"service_tier"},"link":null},{"localized_name":"任务ID","name":"task_ids","type":"STRING","widget":{"name":"task_ids"},"link":null},{"localized_name":"模型选择","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null}],"outputs":[{"localized_name":"查询结果","name":"task_list_json","type":"STRING","links":[9]},{"localized_name":"任务数量","name":"total_tasks","type":"INT","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"7ad8b1aaee36008de7aa83af43457c684ec40cb8","Node name for S&R":"JimengVideoQueryTasks"},"widgets_values":[1,10,"all","default","","all",0,"randomize"]},{"id":27,"type":"JimengReferenceImage2Video","pos":[205.85895782138783,1035.1893951354434],"size":[400,368],"flags":{},"order":5,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":30},{"localized_name":"参考图 1","name":"ref_image_1","shape":7,"type":"IMAGE","link":28},{"localized_name":"参考图 2","name":"ref_image_2","shape":7,"type":"IMAGE","link":29},{"localized_name":"参考图 3","name":"ref_image_3","shape":7,"type":"IMAGE","link":null},{"localized_name":"参考图 4","name":"ref_image_4","shape":7,"type":"IMAGE","link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"FLOAT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值(秒)","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[32]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengReferenceImage2Video"},"widgets_values":["",5,"720p","16:9",true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":20,"type":"LoadImage","pos":[-401.7862338211449,830],"size":[274.080078125,314.00006103515625],"flags":{},"order":0,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[26,28,35]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":21,"type":"LoadImage","pos":[-111.78623382114425,830],"size":[274.080078125,314.00006103515625],"flags":{},"order":1,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[27,29,36]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":26,"type":"JimengSeedance1","pos":[205.85895782138783,389.87173458020527],"size":[400,376],"flags":{},"order":6,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":33},{"localized_name":"首帧图像","name":"image","shape":7,"type":"IMAGE","link":26},{"localized_name":"尾帧图像","name":"last_frame_image","shape":7,"type":"IMAGE","link":27},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"FLOAT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"固定镜头","name":"camerafixed","type":"BOOLEAN","widget":{"name":"camerafixed"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值(秒)","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[31]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengSeedance1"},"widgets_values":["doubao-seedance-1-0-pro","",5,"720p","adaptive",true,true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":3,"type":"SaveVideo","pos":[623.132267622935,389.87173458020527],"size":[270,106],"flags":{},"order":10,"mode":0,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":31},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":5,"type":"SaveVideo","pos":[1346.6645770163816,389.87173458020527],"size":[270,106],"flags":{},"order":11,"mode":4,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":37},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":28,"type":"JimengSeedance1_5","pos":[935.2366868259604,389.87173458020527],"size":[400,448],"flags":{},"order":7,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":34},{"localized_name":"首帧图像","name":"image","shape":7,"type":"IMAGE","link":35},{"localized_name":"尾帧图像","name":"last_frame_image","shape":7,"type":"IMAGE","link":36},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用 Draft 样片模式","name":"draft_mode","type":"BOOLEAN","widget":{"name":"draft_mode"},"link":null},{"localized_name":"复用上次样片任务 ID","name":"reuse_last_draft_task","type":"BOOLEAN","widget":{"name":"reuse_last_draft_task"},"link":null},{"localized_name":"样片任务 ID","name":"draft_task_id","type":"STRING","widget":{"name":"draft_task_id"},"link":null},{"localized_name":"生成音频","name":"generate_audio","type":"BOOLEAN","widget":{"name":"generate_audio"},"link":null},{"localized_name":"智能时长","name":"auto_duration","type":"BOOLEAN","widget":{"name":"auto_duration"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"INT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"固定镜头","name":"camerafixed","type":"BOOLEAN","widget":{"name":"camerafixed"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值(秒)","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[37]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengSeedance1_5"},"widgets_values":["doubao-seedance-1.5-pro","",false,false,"",true,false,5,"720p","adaptive",true,true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":1,"type":"JimengAPIClient","pos":[-100.76525148531957,389.87173458020527],"size":[270,114],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"API Key","name":"new_api_key","type":"STRING","widget":{"name":"new_api_key"},"link":null},{"localized_name":"保存名称 (可选)","name":"new_key_name","type":"STRING","widget":{"name":"new_key_name"},"link":null},{"localized_name":"密钥","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[7,30,33,34]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"7ad8b1aaee36008de7aa83af43457c684ec40cb8","Node name for S&R":"JimengAPIClient"},"widgets_values":["","","Custom"]},{"id":18,"type":"Fast Groups Bypasser (rgthree)","pos":[-40.76525148531957,560],"size":[210,178],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[{"label":"可选连接","name":"OPT_CONNECTION","type":"*","links":null}],"properties":{"matchColors":"","matchTitle":"","showNav":true,"showAllGraphs":true,"sort":"position","customSortAlphabet":"","toggleRestriction":"default"}}],"links":[[7,1,0,8,0,"JIMENG_CLIENT"],[9,8,0,10,0,"STRING"],[26,20,0,26,1,"IMAGE"],[27,21,0,26,2,"IMAGE"],[28,20,0,27,1,"IMAGE"],[29,21,0,27,2,"IMAGE"],[30,1,0,27,0,"JIMENG_CLIENT"],[31,26,0,3,0,"VIDEO"],[32,27,0,7,0,"VIDEO"],[33,1,0,26,0,"JIMENG_CLIENT"],[34,1,0,28,0,"JIMENG_CLIENT"],[35,20,0,28,1,"IMAGE"],[36,21,0,28,2,"IMAGE"],[37,28,0,5,0,"VIDEO"]],"groups":[{"id":1,"title":"Seedance 1.0","bounding":[191.24484729146297,310.9451273255889,708.889585739562,628.981491468161],"color":"#3f789e","font_size":24,"flags":{}},{"id":2,"title":"Seedance 1.5 Pro","bounding":[920.4113766109722,309.91182231470805,709.3349951846517,630.0001987352073],"color":"#3f789e","font_size":24,"flags":{}},{"id":3,"title":"参考图生视频","bounding":[191.39152508563583,960.6862235051547,709.2523972690815,569.335031363257],"color":"#3f789e","font_size":24,"flags":{}},{"id":4,"title":"任务查询","bounding":[920.2499816415618,960.693361122375,709.30261246172,569.0328282889878],"color":"#3f789e","font_size":24,"flags":{}},{"id":5,"title":"图像输入","bounding":[-411.7862338211449,760,581.3555091879997,397.60006103515616],"color":"#3f789e","font_size":24,"flags":{}}],"config":{},"extra":{"ds":{"scale":3.0436707663235394,"offset":[146.35419209123785,-625.9333826202901]},"workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/example_workflows/Seedance.json b/example_workflows/Seedance.json deleted file mode 100644 index eba470f..0000000 --- a/example_workflows/Seedance.json +++ /dev/null @@ -1 +0,0 @@ -{"id":"c6030a59-7432-4d9e-9c27-3a4587d93b75","revision":0,"last_node_id":28,"last_link_id":37,"nodes":[{"id":10,"type":"ShowText|pysssss","pos":[1220.254936410543,1035.1893951354434],"size":[140,26],"flags":{},"order":9,"mode":4,"inputs":[{"label":"文本","localized_name":"文本","name":"text","type":"STRING","link":9}],"outputs":[{"label":"字符串","localized_name":"字符串","name":"STRING","shape":6,"type":"STRING","links":null}],"title":"展示文本","properties":{"cnr_id":"comfyui-custom-scripts","ver":"f2838ed5e59de4d73cde5c98354b87a8d3200190","Node name for S&R":"ShowText|pysssss"},"widgets_values":[]},{"id":7,"type":"SaveVideo","pos":[623.132267622935,1035.1893951354434],"size":[270,106],"flags":{},"order":10,"mode":4,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":32},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":8,"type":"JimengVideoQueryTasks","pos":[934.7428721646523,1035.1893951354434],"size":[270,246],"flags":{},"order":6,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":7},{"localized_name":"页码","name":"page_num","type":"INT","widget":{"name":"page_num"},"link":null},{"localized_name":"每页数量","name":"page_size","type":"INT","widget":{"name":"page_size"},"link":null},{"localized_name":"任务状态","name":"status","type":"COMBO","widget":{"name":"status"},"link":null},{"localized_name":"服务等级","name":"service_tier","type":"COMBO","widget":{"name":"service_tier"},"link":null},{"localized_name":"任务ID","name":"task_ids","type":"STRING","widget":{"name":"task_ids"},"link":null},{"localized_name":"模型选择","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null}],"outputs":[{"localized_name":"查询结果","name":"task_list_json","type":"STRING","links":[9]},{"localized_name":"任务数量","name":"total_tasks","type":"INT","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"7ad8b1aaee36008de7aa83af43457c684ec40cb8","Node name for S&R":"JimengVideoQueryTasks"},"widgets_values":[1,10,"all","default","","all",0,"randomize"]},{"id":27,"type":"JimengReferenceImage2Video","pos":[205.85895782138783,1035.1893951354434],"size":[400,360],"flags":{},"order":7,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":30},{"localized_name":"参考图 1","name":"ref_image_1","shape":7,"type":"IMAGE","link":28},{"localized_name":"参考图 2","name":"ref_image_2","shape":7,"type":"IMAGE","link":29},{"localized_name":"参考图 3","name":"ref_image_3","shape":7,"type":"IMAGE","link":null},{"localized_name":"参考图 4","name":"ref_image_4","shape":7,"type":"IMAGE","link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"FLOAT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[32]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengReferenceImage2Video"},"widgets_values":["",5,"720p","16:9",true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":20,"type":"LoadImage","pos":[-405.5985735159585,778.1176178714351],"size":[274.080078125,314.00006103515625],"flags":{},"order":0,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[26,28,35]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":21,"type":"LoadImage","pos":[-118.32314245295831,778.1176178714351],"size":[274.080078125,314.00006103515625],"flags":{},"order":1,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[27,29,36]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":26,"type":"JimengSeedance1","pos":[205.85895782138783,389.87173458020527],"size":[400,368],"flags":{},"order":8,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":33},{"localized_name":"首帧图像","name":"image","shape":7,"type":"IMAGE","link":26},{"localized_name":"尾帧图像","name":"last_frame_image","shape":7,"type":"IMAGE","link":27},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"FLOAT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"固定镜头","name":"camerafixed","type":"BOOLEAN","widget":{"name":"camerafixed"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[31]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengSeedance1"},"widgets_values":["doubao-seedance-1-0-pro","",5,"720p","adaptive",true,true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":3,"type":"SaveVideo","pos":[623.132267622935,389.87173458020527],"size":[270,106],"flags":{},"order":11,"mode":0,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":31},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":5,"type":"SaveVideo","pos":[1346.6645770163816,389.87173458020527],"size":[270,106],"flags":{},"order":2,"mode":4,"inputs":[{"localized_name":"视频","name":"video","type":"VIDEO","link":37},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"格式","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"编码器","name":"codec","type":"COMBO","widget":{"name":"codec"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.8.2","Node name for S&R":"SaveVideo"},"widgets_values":["Jimeng/Video/Seedance","auto","auto"]},{"id":1,"type":"JimengAPIClient","pos":[-100.76525148531957,389.87173458020527],"size":[270,58],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"密钥名称","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[7,30,33,34]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"7ad8b1aaee36008de7aa83af43457c684ec40cb8","Node name for S&R":"JimengAPIClient"},"widgets_values":["火山引擎 API KEY"]},{"id":28,"type":"JimengSeedance1_5","pos":[935.2366868259604,389.87173458020527],"size":[400,440],"flags":{},"order":5,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":34},{"localized_name":"首帧图像","name":"image","shape":7,"type":"IMAGE","link":35},{"localized_name":"尾帧图像","name":"last_frame_image","shape":7,"type":"IMAGE","link":36},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用 Draft 样片模式","name":"draft_mode","type":"BOOLEAN","widget":{"name":"draft_mode"},"link":null},{"localized_name":"复用上次样片任务 ID","name":"reuse_last_draft_task","type":"BOOLEAN","widget":{"name":"reuse_last_draft_task"},"link":null},{"localized_name":"样片任务 ID","name":"draft_task_id","type":"STRING","widget":{"name":"draft_task_id"},"link":null},{"localized_name":"生成音频","name":"generate_audio","type":"BOOLEAN","widget":{"name":"generate_audio"},"link":null},{"localized_name":"智能时长","name":"auto_duration","type":"BOOLEAN","widget":{"name":"auto_duration"},"link":null},{"localized_name":"时长 (秒)","name":"duration","type":"INT","widget":{"name":"duration"},"link":null},{"localized_name":"分辨率","name":"resolution","type":"COMBO","widget":{"name":"resolution"},"link":null},{"localized_name":"宽高比","name":"aspect_ratio","type":"COMBO","widget":{"name":"aspect_ratio"},"link":null},{"localized_name":"固定镜头","name":"camerafixed","type":"BOOLEAN","widget":{"name":"camerafixed"},"link":null},{"localized_name":"使用随机种子","name":"enable_random_seed","type":"BOOLEAN","widget":{"name":"enable_random_seed"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"保存尾帧","name":"save_last_frame_batch","type":"BOOLEAN","widget":{"name":"save_last_frame_batch"},"link":null},{"localized_name":"任务超时阈值(秒)","name":"timeout_seconds","type":"INT","widget":{"name":"timeout_seconds"},"link":null},{"localized_name":"离线推理模式","name":"enable_offline_inference","type":"BOOLEAN","widget":{"name":"enable_offline_inference"},"link":null},{"localized_name":"非阻塞模式","name":"non_blocking","type":"BOOLEAN","widget":{"name":"non_blocking"},"link":null}],"outputs":[{"localized_name":"视频","name":"video","type":"VIDEO","links":[37]},{"localized_name":"最后一帧","name":"last_frame","type":"IMAGE","links":null},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"e8b1fbf8947a1d399e21ea58759a4ddc3190442f","Node name for S&R":"JimengSeedance1_5"},"widgets_values":["doubao-seedance-1.5-pro","",false,false,"",true,false,5,"720p","adaptive",true,true,0,"randomize",1,"Jimeng/Video/Batch/Seedance",false,172800,false,false]},{"id":18,"type":"Fast Groups Bypasser (rgthree)","pos":[-40.76525148531957,504.59360751252046],"size":[210,178],"flags":{},"order":4,"mode":0,"inputs":[],"outputs":[{"label":"可选连接","name":"OPT_CONNECTION","type":"*","links":null}],"properties":{"matchColors":"","matchTitle":"","showNav":true,"showAllGraphs":true,"sort":"position","customSortAlphabet":"","toggleRestriction":"default"}}],"links":[[7,1,0,8,0,"JIMENG_CLIENT"],[9,8,0,10,0,"STRING"],[26,20,0,26,1,"IMAGE"],[27,21,0,26,2,"IMAGE"],[28,20,0,27,1,"IMAGE"],[29,21,0,27,2,"IMAGE"],[30,1,0,27,0,"JIMENG_CLIENT"],[31,26,0,3,0,"VIDEO"],[32,27,0,7,0,"VIDEO"],[33,1,0,26,0,"JIMENG_CLIENT"],[34,1,0,28,0,"JIMENG_CLIENT"],[35,20,0,28,1,"IMAGE"],[36,21,0,28,2,"IMAGE"],[37,28,0,5,0,"VIDEO"]],"groups":[{"id":1,"title":"Seedance 1.0","bounding":[191.24484729146297,310.9451273255889,708.889585739562,628.981491468161],"color":"#3f789e","font_size":24,"flags":{}},{"id":2,"title":"Seedance 1.5 Pro","bounding":[920.4113766109722,309.91182231470805,709.3349951846517,630.0001987352073],"color":"#3f789e","font_size":24,"flags":{}},{"id":3,"title":"参考图生视频","bounding":[191.39152508563583,960.6862235051547,709.2523972690815,569.335031363257],"color":"#3f789e","font_size":24,"flags":{}},{"id":4,"title":"任务查询","bounding":[920.2499816415618,960.693361122375,709.30261246172,569.0328282889878],"color":"#3f789e","font_size":24,"flags":{}},{"id":5,"title":"图像输入","bounding":[-415.5985735159585,704.517617871435,581.3555091879997,397.60006103515616],"color":"#3f789e","font_size":24,"flags":{}}],"config":{},"extra":{"ds":{"scale":0.7286305823552036,"offset":[443.9685750776844,-191.0099352013512]},"workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/example_workflows/Seedance.png b/example_workflows/Seedance.png deleted file mode 100644 index 8c8a19a..0000000 Binary files a/example_workflows/Seedance.png and /dev/null differ diff --git a/example_workflows/Seedream 3.jpg b/example_workflows/Seedream 3.jpg new file mode 100644 index 0000000..79c4903 Binary files /dev/null and b/example_workflows/Seedream 3.jpg differ diff --git a/example_workflows/Seedream 3.json b/example_workflows/Seedream 3.json index 3eb501f..ffc36ae 100644 --- a/example_workflows/Seedream 3.json +++ b/example_workflows/Seedream 3.json @@ -1 +1 @@ -{"id":"b28f4690-74e9-4dab-b3d1-53c5a902c792","revision":0,"last_node_id":27,"last_link_id":20,"nodes":[{"id":26,"type":"SaveImage","pos":[1541.6278557861083,340.2462487798781],"size":[270,58],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":20},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.10.0","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream3"]},{"id":21,"type":"JimengAPIClient","pos":[836.7208274647576,340.2462487798781],"size":[270,58],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"密钥名称","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[19]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengAPIClient"},"widgets_values":["火山引擎 API KEY"]},{"id":27,"type":"JimengSeedream3","pos":[1122.1558251871058,340.2462487798781],"size":[400,308],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":19},{"localized_name":"输入图像","name":"image","shape":7,"type":"IMAGE","link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"引导系数","name":"guidance_scale","type":"FLOAT","widget":{"name":"guidance_scale"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"image","type":"IMAGE","links":[20]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream3"},"widgets_values":["",5,"Custom",1024,1024,0,"randomize",1,false]}],"links":[[19,21,0,27,0,"JIMENG_CLIENT"],[20,27,0,26,0,"IMAGE"]],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[-418.3782143681733,-27.50677099728992]},"workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"b28f4690-74e9-4dab-b3d1-53c5a902c792","revision":0,"last_node_id":27,"last_link_id":20,"nodes":[{"id":26,"type":"SaveImage","pos":[1541.6278557861083,340.2462487798781],"size":[270,58],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":20},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.10.0","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream3"]},{"id":27,"type":"JimengSeedream3","pos":[1122.1558251871058,340.2462487798781],"size":[400,308],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":19},{"localized_name":"输入图像","name":"image","shape":7,"type":"IMAGE","link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"引导系数","name":"guidance_scale","type":"FLOAT","widget":{"name":"guidance_scale"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"image","type":"IMAGE","links":[20]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream3"},"widgets_values":["",5,"Custom",1024,1024,0,"randomize",1,false]},{"id":21,"type":"JimengAPIClient","pos":[836.7208274647576,340.2462487798781],"size":[270,114],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"API Key","name":"new_api_key","type":"STRING","widget":{"name":"new_api_key"},"link":null},{"localized_name":"保存名称 (可选)","name":"new_key_name","type":"STRING","widget":{"name":"new_key_name"},"link":null},{"localized_name":"密钥","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[19]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengAPIClient"},"widgets_values":["","","Custom"]}],"links":[[19,21,0,27,0,"JIMENG_CLIENT"],[20,27,0,26,0,"IMAGE"]],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[-418.3782143681733,-27.50677099728992]},"workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/example_workflows/Seedream 3.png b/example_workflows/Seedream 3.png deleted file mode 100644 index 0163d8e..0000000 Binary files a/example_workflows/Seedream 3.png and /dev/null differ diff --git a/example_workflows/Seedream 4.jpg b/example_workflows/Seedream 4.jpg new file mode 100644 index 0000000..11d7380 Binary files /dev/null and b/example_workflows/Seedream 4.jpg differ diff --git a/example_workflows/Seedream 4.json b/example_workflows/Seedream 4.json index e0143fe..2dd7176 100644 --- a/example_workflows/Seedream 4.json +++ b/example_workflows/Seedream 4.json @@ -1 +1 @@ -{"id":"f477984c-0d7e-476e-8f0b-5a312c5d9de4","revision":0,"last_node_id":71,"last_link_id":72,"nodes":[{"id":56,"type":"LoadImage","pos":[403.8779616701457,894.1960938038201],"size":[274.080078125,314.00006103515625],"flags":{},"order":0,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[57]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":52,"type":"ImageBatch","pos":[708.2405608914196,890.8520850065952],"size":[140,46],"flags":{},"order":10,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":56},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":57}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[58]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":60,"type":"LoadImage","pos":[404.4626802814491,1262.330924075425],"size":[274.080078125,314.00006103515625],"flags":{},"order":1,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[63]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":59,"type":"LoadImage","pos":[107.90276825370063,1262.330924075425],"size":[274.080078125,314.00006103515625],"flags":{},"order":2,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[62]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":61,"type":"ImageBatch","pos":[700.1851245412977,1109.0743225497088],"size":[140,46],"flags":{},"order":9,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":62},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":63}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[64]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":55,"type":"LoadImage","pos":[107.31804964239745,894.1960938038201],"size":[274.080078125,314.00006103515625],"flags":{},"order":3,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[56]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":64,"type":"SaveImage","pos":[1375.2661588286,894.3323492425179],"size":[270,270],"flags":{},"order":16,"mode":4,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":67},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":66,"type":"SaveImage","pos":[1374.4190717205101,1232.5343091724878],"size":[270,270],"flags":{},"order":17,"mode":4,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":68},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":62,"type":"Note","pos":[700.6778213812852,1206.0662024801222],"size":[210,88],"flags":{},"order":4,"mode":4,"inputs":[],"outputs":[],"title":"注释","properties":{},"widgets_values":["Seedream 4 模型支持最多14张参考图片作为输入。\n可以使用批量图片创建图片批次作为输入图片。"],"color":"#432","bgcolor":"#653"},{"id":68,"type":"Note","pos":[962.9002640233265,1556.5135415990794],"size":[210,88],"flags":{},"order":5,"mode":4,"inputs":[],"outputs":[],"title":"注释","properties":{},"widgets_values":["节点支持异步提交任务。"],"color":"#432","bgcolor":"#653"},{"id":65,"type":"JimengSeedream4","pos":[960.8241941225891,894.3323492425179],"size":[400,284],"flags":{},"order":12,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":69},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":null},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[67]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":67,"type":"JimengSeedream4","pos":[959.9771070144982,1232.5343091724878],"size":[400,284],"flags":{},"order":13,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":70},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":null},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[68]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":45,"type":"SaveImage","pos":[1373.6983932040014,463.59812563578726],"size":[274,273],"flags":{},"order":15,"mode":0,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":55},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":53,"type":"ImageBatch","pos":[700.4976252838048,1004.6094435125451],"size":[190.78903627371085,46],"flags":{},"order":14,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":58},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":64}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":63,"type":"LoadImage","pos":[645.1550199085696,463.7512706505751],"size":[274.080078125,314.00006103515625],"flags":{},"order":6,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[72]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":51,"type":"JimengAPIClient","pos":[345.22817480337403,464.9328410985913],"size":[270,58],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"密钥名称","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[54,69,70]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengAPIClient"},"widgets_values":["火山引擎 API KEY"]},{"id":50,"type":"JimengSeedream4","pos":[959.2564284979915,463.59812563578726],"size":[401.30657820983856,284],"flags":{},"order":11,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":54},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":72},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[55]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":71,"type":"Fast Groups Bypasser (rgthree)","pos":[367.93266699087405,583.5635803813957],"size":[247.2955078125,154],"flags":{},"order":8,"mode":0,"inputs":[],"outputs":[{"label":"可选连接","name":"OPT_CONNECTION","type":"*","links":null}],"properties":{"matchColors":"","matchTitle":"","showNav":true,"showAllGraphs":true,"sort":"position","customSortAlphabet":"","toggleRestriction":"default"}}],"links":[[54,51,0,50,0,"JIMENG_CLIENT"],[55,50,0,45,0,"IMAGE"],[56,55,0,52,0,"IMAGE"],[57,56,0,52,1,"IMAGE"],[58,52,0,53,0,"IMAGE"],[62,59,0,61,0,"IMAGE"],[63,60,0,61,1,"IMAGE"],[64,61,0,53,1,"IMAGE"],[67,65,0,64,0,"IMAGE"],[68,67,0,66,0,"IMAGE"],[69,51,0,65,0,"JIMENG_CLIENT"],[70,51,0,67,0,"JIMENG_CLIENT"],[72,63,0,50,1,"IMAGE"]],"groups":[{"id":1,"title":"组图输入","bounding":[97.31804964239748,820.5960938038202,832.2197835758179,763.2826181887953],"color":"#3f789e","font_size":24,"flags":{}},{"id":2,"title":"单图输入","bounding":[635.1550199085696,390.1512706505758,293.56692000676935,408.37638151800087],"color":"#3f789e","font_size":24,"flags":{}},{"id":3,"title":"批量处理","bounding":[949.9771070144982,820.7323492425179,709.379830603923,838.5099292772201],"color":"#3f789e","font_size":24,"flags":{}},{"id":4,"title":"单任务","bounding":[949.2564284979915,389.9981256357873,710.3819547466364,409.9349518051278],"color":"#3f789e","font_size":24,"flags":{}}],"config":{},"extra":{"ds":{"scale":0.8264462809917359,"offset":[-388.6501998066519,43.96380282101393]},"frontendVersion":"1.18.9","workflowRendererVersion":"LG","VHS_latentpreview":false,"VHS_latentpreviewrate":0,"VHS_MetadataImage":true,"VHS_KeepIntermediate":true},"version":0.4} \ No newline at end of file +{"id":"f477984c-0d7e-476e-8f0b-5a312c5d9de4","revision":0,"last_node_id":71,"last_link_id":72,"nodes":[{"id":56,"type":"LoadImage","pos":[403.8779616701457,894.1960938038201],"size":[274.080078125,314.00006103515625],"flags":{},"order":0,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[57]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":52,"type":"ImageBatch","pos":[708.2405608914196,890.8520850065952],"size":[140,46],"flags":{},"order":10,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":56},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":57}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[58]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":60,"type":"LoadImage","pos":[404.4626802814491,1262.330924075425],"size":[274.080078125,314.00006103515625],"flags":{},"order":1,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[63]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":59,"type":"LoadImage","pos":[107.90276825370063,1262.330924075425],"size":[274.080078125,314.00006103515625],"flags":{},"order":2,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[62]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":61,"type":"ImageBatch","pos":[700.1851245412977,1109.0743225497088],"size":[140,46],"flags":{},"order":9,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":62},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":63}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[64]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":55,"type":"LoadImage","pos":[107.31804964239745,894.1960938038201],"size":[274.080078125,314.00006103515625],"flags":{},"order":3,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[56]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":64,"type":"SaveImage","pos":[1375.2661588286,894.3323492425179],"size":[270,270],"flags":{},"order":16,"mode":4,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":67},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":66,"type":"SaveImage","pos":[1374.4190717205101,1232.5343091724878],"size":[270,270],"flags":{},"order":17,"mode":4,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":68},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":62,"type":"Note","pos":[700.6778213812852,1206.0662024801222],"size":[210,88],"flags":{},"order":4,"mode":4,"inputs":[],"outputs":[],"title":"注释","properties":{},"widgets_values":["Seedream 4 模型支持最多14张参考图片作为输入。\n可以使用批量图片创建图片批次作为输入图片。"],"color":"#432","bgcolor":"#653"},{"id":68,"type":"Note","pos":[962.9002640233265,1556.5135415990794],"size":[210,88],"flags":{},"order":5,"mode":4,"inputs":[],"outputs":[],"title":"注释","properties":{},"widgets_values":["节点支持异步提交任务。"],"color":"#432","bgcolor":"#653"},{"id":65,"type":"JimengSeedream4","pos":[960.8241941225891,894.3323492425179],"size":[400,284],"flags":{},"order":12,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":69},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":null},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[67]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":67,"type":"JimengSeedream4","pos":[959.9771070144982,1232.5343091724878],"size":[400,284],"flags":{},"order":13,"mode":4,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":70},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":null},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[68]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":45,"type":"SaveImage","pos":[1373.6983932040014,463.59812563578726],"size":[274,273],"flags":{},"order":15,"mode":0,"inputs":[{"localized_name":"图片","name":"images","type":"IMAGE","link":55},{"localized_name":"文件名前缀","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfy-core","ver":"0.3.65","Node name for S&R":"SaveImage"},"widgets_values":["Jimeng/Image/Seedream4"]},{"id":53,"type":"ImageBatch","pos":[700.4976252838048,1004.6094435125451],"size":[190.78903627371085,46],"flags":{},"order":14,"mode":4,"inputs":[{"localized_name":"图像1","name":"image1","type":"IMAGE","link":58},{"localized_name":"图像2","name":"image2","type":"IMAGE","link":64}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[]}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"ImageBatch"},"widgets_values":[]},{"id":63,"type":"LoadImage","pos":[645.1550199085696,463.7512706505751],"size":[274.080078125,314.00006103515625],"flags":{},"order":6,"mode":4,"inputs":[{"localized_name":"图像","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"选择文件上传","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"图像","name":"IMAGE","type":"IMAGE","links":[72]},{"localized_name":"遮罩","name":"MASK","type":"MASK","links":null}],"properties":{"cnr_id":"comfy-core","ver":"0.3.52","Node name for S&R":"LoadImage"},"widgets_values":["comfyui_logo.png","image"]},{"id":50,"type":"JimengSeedream4","pos":[959.2564284979915,463.59812563578726],"size":[401.30657820983856,284],"flags":{},"order":11,"mode":0,"inputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","link":54},{"localized_name":"输入图像","name":"images","shape":7,"type":"IMAGE","link":72},{"localized_name":"模型版本","name":"model_version","type":"COMBO","widget":{"name":"model_version"},"link":null},{"localized_name":"提示词","name":"prompt","type":"STRING","widget":{"name":"prompt"},"link":null},{"localized_name":"启用组图生成","name":"enable_group_generation","type":"BOOLEAN","widget":{"name":"enable_group_generation"},"link":null},{"localized_name":"最大图片数","name":"max_images","type":"INT","widget":{"name":"max_images"},"link":null},{"localized_name":"尺寸","name":"size","type":"COMBO","widget":{"name":"size"},"link":null},{"localized_name":"宽度","name":"width","type":"INT","widget":{"name":"width"},"link":null},{"localized_name":"高度","name":"height","type":"INT","widget":{"name":"height"},"link":null},{"localized_name":"种子","name":"seed","type":"INT","widget":{"name":"seed"},"link":null},{"localized_name":"生成数量","name":"generation_count","type":"INT","widget":{"name":"generation_count"},"link":null},{"localized_name":"水印","name":"watermark","type":"BOOLEAN","widget":{"name":"watermark"},"link":null}],"outputs":[{"localized_name":"图像","name":"images","type":"IMAGE","links":[55]},{"localized_name":"响应","name":"response","type":"STRING","links":null}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengSeedream4"},"widgets_values":["doubao-seedream-4.5","",false,1,"2K (adaptive)",2048,2048,0,"randomize",1,false]},{"id":71,"type":"Fast Groups Bypasser (rgthree)","pos":[367.93266699087405,634.5635803813957],"size":[247.2955078125,154],"flags":{},"order":8,"mode":0,"inputs":[],"outputs":[{"label":"可选连接","name":"OPT_CONNECTION","type":"*","links":null}],"properties":{"matchColors":"","matchTitle":"","showNav":true,"showAllGraphs":true,"sort":"position","customSortAlphabet":"","toggleRestriction":"default"}},{"id":51,"type":"JimengAPIClient","pos":[345.22817480337403,464.9328410985913],"size":[270,114],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"API Key","name":"new_api_key","type":"STRING","widget":{"name":"new_api_key"},"link":null},{"localized_name":"保存名称 (可选)","name":"new_key_name","type":"STRING","widget":{"name":"new_key_name"},"link":null},{"localized_name":"密钥","name":"key_name","type":"COMBO","widget":{"name":"key_name"},"link":null}],"outputs":[{"localized_name":"客户端","name":"client","type":"JIMENG_CLIENT","links":[54,69,70]}],"properties":{"cnr_id":"ComfyUI-Jimeng-API","ver":"283c3afa7c08b5f80dcfb4c2b2c035f8308fb65a","Node name for S&R":"JimengAPIClient"},"widgets_values":["","","Custom"]}],"links":[[54,51,0,50,0,"JIMENG_CLIENT"],[55,50,0,45,0,"IMAGE"],[56,55,0,52,0,"IMAGE"],[57,56,0,52,1,"IMAGE"],[58,52,0,53,0,"IMAGE"],[62,59,0,61,0,"IMAGE"],[63,60,0,61,1,"IMAGE"],[64,61,0,53,1,"IMAGE"],[67,65,0,64,0,"IMAGE"],[68,67,0,66,0,"IMAGE"],[69,51,0,65,0,"JIMENG_CLIENT"],[70,51,0,67,0,"JIMENG_CLIENT"],[72,63,0,50,1,"IMAGE"]],"groups":[{"id":1,"title":"组图输入","bounding":[97.31804964239748,820.5960938038202,832.2197835758179,763.2826181887953],"color":"#3f789e","font_size":24,"flags":{}},{"id":2,"title":"单图输入","bounding":[635.1550199085696,390.1512706505758,293.56692000676935,408.37638151800087],"color":"#3f789e","font_size":24,"flags":{}},{"id":3,"title":"批量处理","bounding":[949.9771070144982,820.7323492425179,709.379830603923,838.5099292772201],"color":"#3f789e","font_size":24,"flags":{}},{"id":4,"title":"单任务","bounding":[949.2564284979915,389.9981256357873,710.3819547466364,409.9349518051278],"color":"#3f789e","font_size":24,"flags":{}}],"config":{},"extra":{"ds":{"scale":0.5944762272417989,"offset":[601.9846846272567,-176.39452560357117]},"frontendVersion":"1.18.9","workflowRendererVersion":"LG","VHS_latentpreview":false,"VHS_latentpreviewrate":0,"VHS_MetadataImage":true,"VHS_KeepIntermediate":true},"version":0.4} \ No newline at end of file diff --git a/example_workflows/Seedream 4.png b/example_workflows/Seedream 4.png deleted file mode 100644 index 0ec66d6..0000000 Binary files a/example_workflows/Seedream 4.png and /dev/null differ diff --git a/locales/zh/nodeDefs.json b/locales/zh/nodeDefs.json index 6ec58ea..dbcd9b3 100644 --- a/locales/zh/nodeDefs.json +++ b/locales/zh/nodeDefs.json @@ -4,8 +4,16 @@ "description": "加载 `api_keys.json` 文件中指定的 API 密钥,并创建一个可供其他节点使用的客户端实例。", "inputs": { "key_name": { - "name": "密钥名称", - "tooltip": "在 api_keys.json 中配置的自定义密钥名称。" + "name": "密钥", + "tooltip": "在 api_keys.json 中配置的密钥。" + }, + "new_api_key": { + "name": "API Key", + "tooltip": "在此处粘贴您在火山方舟创建的 API Key。" + }, + "new_key_name": { + "name": "保存名称 (可选)", + "tooltip": "若填写此项,API Key 将被保存到 api_keys.json 中。注意:保存后需刷新浏览器页面,新密钥才会显示在下拉列表中。" } }, "outputs": { diff --git a/nodes/constants.py b/nodes/constants.py index e271726..451a6d6 100644 --- a/nodes/constants.py +++ b/nodes/constants.py @@ -30,79 +30,81 @@ DEFAULT_FILENAME_PREFIX = "Jimeng/Video/Batch/Seedance" LOG_TRANSLATIONS = { "zh": { # 初始化/依赖检查相关 - "init_sdk_ver_low": "[JimengAI] 当前 SDK 版本 {current} 过低,正在自动更新至 >= {min}...", - "init_sdk_update_ok": "[JimengAI] SDK 更新完成。", - "init_sdk_not_found": "[JimengAI] 未检测到 {pkg},正在自动安装...", - "init_sdk_install_ok": "[JimengAI] SDK 安装完成。", - "init_sdk_install_fail": "[JimengAI] 自动安装失败,请手动安装: {e}", - "init_dep_check_err": "[JimengAI] 依赖检查出错: {e}", + "init_sdk_ver_low": "当前 SDK 版本 {current} 过低,正在自动更新至 >= {min}...", + "init_sdk_update_ok": "SDK 更新完成。", + "init_sdk_not_found": "未检测到 {pkg},正在自动安装...", + "init_sdk_install_ok": "SDK 安装完成。", + "init_sdk_install_fail": "自动安装失败,请手动安装: {e}", + "init_dep_check_err": "依赖检查出错: {e}", # 控制台信息 - "api_file_not_found": "[JimengAI] 提示: 未找到 API 密钥文件。请将 'api_keys.json.example' 重命名为 'api_keys.json' 并填入您的密钥。", - "api_file_empty": "[JimengAI] 警告: 'api_keys.json' 为空或格式不正确。", - "api_load_error": "[JimengAI] 错误: 加载 'api_keys.json' 失败: {e}", - "api_key_not_found": "[JimengAI] 错误: 未找到 '{key_name}' 的 API Key,请检查配置文件。", + "api_file_not_found": "提示: 未找到 API 密钥文件。请将 'api_keys.json.example' 重命名为 'api_keys.json' 并填入您的密钥。", + "api_file_empty": "警告: 'api_keys.json' 为空或格式不正确。", + "api_load_error": "错误: 加载 'api_keys.json' 失败: {e}", + "api_key_not_found": "错误: 未找到 '{key_name}' 的 API Key,请检查配置文件。", "est_fallback": "默认兜底", "est_history": "历史均值", "est_regression": "线性回归", "est_recent": "近期负载调整", - "task_submitted_est": "[JimengAI] 任务已提交。预估生成时间: {time}s (预估方式: {method})", - "task_info_simple": "[JimengAI] 任务 ID: {task_id} | 模型: {model}", - "batch_submit_start": "[JimengAI] 正在提交 {count} 个任务...", - "batch_submit_result": "[JimengAI] 提交完成。成功: {created},失败: {failed}。", - "batch_failed_summary": "[JimengAI] ⚠️ {count} 个任务创建失败。原因汇总:", + "task_submitted_est": "任务已提交。预估生成时间: {time}s (预估方式: {method})", + "task_info_simple": "任务 ID: {task_id} | 模型: {model}", + "batch_submit_start": "正在提交 {count} 个任务...", + "batch_submit_result": "提交完成。成功: {created},失败: {failed}。", + "batch_failed_summary": "⚠️ {count} 个任务创建失败。原因汇总:", "batch_failed_reason": " - {msg}: {count} 次", # 轮询提示 - "polling_single": "[JimengAI] 任务 {task_id}: 运行中... 已耗时 {elapsed}s / 预估 {max}s", - "polling_single_waiting": "[JimengAI] 任务排队等待资源中... (状态: {status})", - "polling_batch_stats": "[JimengAI] 批量进度: 完成 {done}/{total}。等待中: {pending}... (耗时 {elapsed}s / 预估 {max}s) [运行中: {running},排队: {queued}]", + "polling_single": "任务 {task_id}: 运行中... 已耗时 {elapsed}s / 预估 {max}s", + "polling_single_waiting": "任务排队等待资源中... (状态: {status})", + "polling_batch_stats": "批量进度: 完成 {done}/{total}。等待中: {pending}... (耗时 {elapsed}s / 预估 {max}s) [运行中: {running},排队: {queued}]", - "interrupted": "\n[JimengAI] 用户中断了处理。正在尝试取消挂起任务...", - "cancel_task_success": "[JimengAI] 已成功取消任务: {task_id}", - "cancel_task_failed": "[JimengAI] 取消任务 {task_id} 失败: {msg}", - "cancel_batch_summary": "[JimengAI] 批量取消完成。成功取消: {success} 个,取消失败: {failed} 个。", + "interrupted": "\n" + "用户中断了处理。正在尝试取消挂起任务...", + "cancel_task_success": "已成功取消任务: {task_id}", + "cancel_task_failed": "取消任务 {task_id} 失败: {msg}", + "cancel_batch_summary": "批量取消完成。成功取消: {success} 个,取消失败: {failed} 个。", "cancel_batch_reason": " - {msg}", - "task_finished_single": "[JimengAI] 任务执行成功。", - "batch_finished_stats": "[JimengAI] 批量处理完成。成功: {success},失败: {failed}。", - "batch_handling": "[JimengAI] 正在处理 {count} 个成功任务,按 Seed 排序并下载...", - "batch_copying": "[JimengAI] 正在保存文件到输出目录: {path}", - "err_download_url": "[JimengAI] 异步下载或转换失败,URL: {url},错误: {e}", - "err_task_create": "[JimengAI] 任务创建失败: {e}", - "err_task_check": "[JimengAI] 检查任务状态失败 ({tid}): {e}", - "err_task_fail_msg": "[JimengAI] 任务 {tid} 失败: {msg}", - "err_batch_fail_all": "[JimengAI] 批量任务失败: 无任务成功。", - "err_copy_fail": "[JimengAI] 复制文件失败: {path},错误: {e}", - "err_convert_tensor": "[JimengAI] 转换图片 Tensor 失败: {e}", - "err_check_status_batch": "[JimengAI] 检查非阻塞任务状态失败: {e}", - "download_retry": "[JimengAI] 警告: 下载失败 (尝试 {attempt}/{total})。{delay}秒后重试... 错误: {e}", + "task_finished_single": "任务执行成功。", + "batch_finished_stats": "批量处理完成。成功: {success},失败: {failed}。", + "batch_handling": "正在处理 {count} 个成功任务,按 Seed 排序并下载...", + "batch_copying": "正在保存文件到输出目录: {path}", + "err_download_url": "异步下载或转换失败,URL: {url},错误: {e}", + "err_task_create": "任务创建失败: {e}", + "err_task_check": "检查任务状态失败 ({tid}): {e}", + "err_task_fail_msg": "任务 {tid} 失败: {msg}", + "err_batch_fail_all": "批量任务失败: 无任务成功。", + "err_copy_fail": "复制文件失败: {path},错误: {e}", + "err_convert_tensor": "转换图片 Tensor 失败: {e}", + "err_check_status_batch": "检查非阻塞任务状态失败: {e}", + "download_retry": "警告: 下载失败 (尝试 {attempt}/{total})。{delay}秒后重试... 错误: {e}", # 流式生成 - "stream_recv_image": "[JimengAI] 流式接收: 第 {index} 张图片生成完毕,正在后台下载...", - "stream_partial_fail": "[JimengAI] 流式警告: 第 {index} 张图片生成失败: {msg}", + "stream_recv_image": "流式接收: 第 {index} 张图片生成完毕,正在后台下载...", + "stream_partial_fail": "流式警告: 第 {index} 张图片生成失败: {msg}", # 弹窗提示 - "popup_req_failed": "[JimengAI] 请求失败: {msg}", - "popup_task_failed": "[JimengAI] 任务 {task_id} 失败: {msg}", - "popup_batch_pending": "[JimengAI] 批量任务 ({count} 个) 处理中。请再次运行以检查结果。", - "popup_task_pending": "[JimengAI] 任务 {task_id} 状态为 {status}。请再次运行以检查结果。", - "popup_param_not_allowed": "[JimengAI] 参数错误: 提示词中不允许包含参数 '--{param}'。请使用节点的组件进行设置。", - "popup_first_frame_missing": "[JimengAI] 参数错误: 使用尾帧图片时必须提供首帧图片。", - "popup_ref_missing": "[JimengAI] 参数错误: 必须提供至少一张参考图。", - "popup_prepare_failed": "[JimengAI] 任务准备失败: {e}", + "popup_req_failed": "请求失败: {msg}", + "popup_task_failed": "任务 {task_id} 失败: {msg}", + "popup_batch_pending": "批量任务 ({count} 个) 处理中。请再次运行以检查结果。", + "popup_task_pending": "任务 {task_id} 状态为 {status}。请再次运行以检查结果。", + "popup_param_not_allowed": "参数错误: 提示词中不允许包含参数 '--{param}'。请使用节点的组件进行设置。", + "popup_first_frame_missing": "参数错误: 使用尾帧图片时必须提供首帧图片。", + "popup_ref_missing": "参数错误: 必须提供至少一张参考图。", + "popup_prepare_failed": "任务准备失败: {e}", # 图片节点 - "err_pixels_range": "[JimengAI] 参数错误: 总像素数必须在 {min} ({min_desc}) 和 {max} ({max_desc}) 之间。当前值: {current}", - "err_aspect_ratio": "[JimengAI] 参数错误: 宽高比必须在 {min} 和 {max} 之间。当前值: {current}", - "err_download_img": "[JimengAI] 错误: 下载生成的图像失败。", - "err_gen_model": "[JimengAI] 模型 {model} 生成失败: {e}", - "err_img_limit_10": "[JimengAI] 参数错误: 输入图像数量不能超过 10 张。", - "err_img_limit_15": "[JimengAI] 参数错误: 输入图像数 ({n}) 与最大生成数 ({max}) 之和不能超过 15。", - "err_img_limit_group_15": "[JimengAI] 参数错误: 在组图模式下,输入参考图数量 ({n}) 加 生成图片数量 ({max}) 的总和 ({total}) 不能超过 15 张。", + "err_pixels_range": "参数错误: 总像素数必须在 {min} ({min_desc}) 和 {max} ({max_desc}) 之间。当前值: {current}", + "err_aspect_ratio": "参数错误: 宽高比必须在 {min} 和 {max} 之间。当前值: {current}", + "err_download_img": "错误: 下载生成的图像失败。", + "err_gen_model": "模型 {model} 生成失败: {e}", + "err_img_limit_10": "参数错误: 输入图像数量不能超过 10 张。", + "err_img_limit_15": "参数错误: 输入图像数 ({n}) 与最大生成数 ({max}) 之和不能超过 15。", + "err_img_limit_group_15": "参数错误: 在组图模式下,输入参考图数量 ({n}) 加 生成图片数量 ({max}) 的总和 ({total}) 不能超过 15 张。", # Keys - "combo_no_keys": "未找到密钥 (请配置 api_keys.json)", - "popup_key_valid_err": "[JimengAI] 配置错误: 所选密钥 '{key}' 无效或未找到。请检查 api_keys.json。", + "popup_key_valid_err": "配置错误: 所选密钥 '{key}' 无效或未找到。请检查 api_keys.json。", + "err_new_key_empty": "配置错误: 已启用手动输入,但 API Key 为空。", + "err_new_key_invalid": "鉴权失败: 输入的 API Key 无效,请检查 Key 是否正确。", + "info_new_key_saved": "提示: 新密钥 '{name}' 已通过鉴权并保存到 api_keys.json。", # API 错误码映射 "api_errors": { @@ -133,69 +135,71 @@ LOG_TRANSLATIONS = { } }, "en": { - "init_sdk_ver_low": "[JimengAI] Current SDK version {current} is too low. Auto-updating to >= {min}...", - "init_sdk_update_ok": "[JimengAI] SDK update completed.", - "init_sdk_not_found": "[JimengAI] Package {pkg} not found. Installing automatically...", - "init_sdk_install_ok": "[JimengAI] SDK installation completed.", - "init_sdk_install_fail": "[JimengAI] Auto-install failed. Please install manually: {e}", - "init_dep_check_err": "[JimengAI] Dependency check error: {e}", - "api_file_not_found": "[JimengAI] Info: API keys file not found. Please rename 'api_keys.json.example' to 'api_keys.json' and fill in your keys.", - "api_file_empty": "[JimengAI] Warning: 'api_keys.json' is empty or not formatted correctly.", - "api_load_error": "[JimengAI] Error: Failed to load 'api_keys.json': {e}", - "api_key_not_found": "[JimengAI] Error: API Key for '{key_name}' not found.", + "init_sdk_ver_low": "Current SDK version {current} is too low. Auto-updating to >= {min}...", + "init_sdk_update_ok": "SDK update completed.", + "init_sdk_not_found": "Package {pkg} not found. Installing automatically...", + "init_sdk_install_ok": "SDK installation completed.", + "init_sdk_install_fail": "Auto-install failed. Please install manually: {e}", + "init_dep_check_err": "Dependency check error: {e}", + "api_file_not_found": "Info: API keys file not found. Please rename 'api_keys.json.example' to 'api_keys.json' and fill in your keys.", + "api_file_empty": "Warning: 'api_keys.json' is empty or not formatted correctly.", + "api_load_error": "Error: Failed to load 'api_keys.json': {e}", + "api_key_not_found": "Error: API Key for '{key_name}' not found.", "est_fallback": "Fallback Default", "est_history": "History Average", "est_regression": "Linear Regression", "est_recent": "Recent Load Adjustment", - "task_submitted_est": "[JimengAI] Task submitted. Est. time: {time}s (Method: {method})", - "task_info_simple": "[JimengAI] Task ID: {task_id} | Model: {model}", - "batch_submit_start": "[JimengAI] Submitting batch of {count} tasks (Model: {model})...", - "batch_submit_result": "[JimengAI] Submission complete. Created: {created}, Failed: {failed}.", - "batch_failed_summary": "[JimengAI] ⚠️ {count} tasks failed to create. Reason summary:", + "task_submitted_est": "Task submitted. Est. time: {time}s (Method: {method})", + "task_info_simple": "Task ID: {task_id} | Model: {model}", + "batch_submit_start": "Submitting batch of {count} tasks (Model: {model})...", + "batch_submit_result": "Submission complete. Created: {created}, Failed: {failed}.", + "batch_failed_summary": "⚠️ {count} tasks failed to create. Reason summary:", "batch_failed_reason": " - {msg}: {count} times", # Updated - "polling_single": "[JimengAI] Task {task_id}: Running... {elapsed}s / {max}s elapsed", - "polling_single_waiting": "[JimengAI] Task {task_id}: Queued and waiting for resources... (Status: {status})", - "polling_batch_stats": "[JimengAI] Batch Progress: {done}/{total} done. {pending} pending... (Elapsed {elapsed}s / {max}s) [Run: {running}, Queue: {queued}]", + "polling_single": "Task {task_id}: Running... {elapsed}s / {max}s elapsed", + "polling_single_waiting": "Task {task_id}: Queued and waiting for resources... (Status: {status})", + "polling_batch_stats": "Batch Progress: {done}/{total} done. {pending} pending... (Elapsed {elapsed}s / {max}s) [Run: {running}, Queue: {queued}]", - "interrupted": "\n[JimengAI] Processing interrupted by user. Cancelling pending tasks...", - "cancel_task_success": "[JimengAI] Successfully cancelled task: {task_id}", - "cancel_task_failed": "[JimengAI] Failed to cancel task {task_id}: {msg}", - "cancel_batch_summary": "[JimengAI] Batch cancellation finished. Success: {success}, Failed: {failed}.", + "interrupted": "\n" + "Processing interrupted by user. Cancelling pending tasks...", + "cancel_task_success": "Successfully cancelled task: {task_id}", + "cancel_task_failed": "Failed to cancel task {task_id}: {msg}", + "cancel_batch_summary": "Batch cancellation finished. Success: {success}, Failed: {failed}.", "cancel_batch_reason": " - {msg}", - "task_finished_single": "[JimengAI] Task completed successfully.", - "batch_finished_stats": "[JimengAI] Batch finished. Success: {success}, Failed: {failed}.", - "batch_handling": "[JimengAI] Handling {count} successful tasks. Sorting by seed and downloading...", - "batch_copying": "[JimengAI] Copying files to output directory: {path}", - "err_download_url": "[JimengAI] Async download failed, URL: {url}, Error: {e}", - "err_task_create": "[JimengAI] Task creation failed: {e}", - "err_task_check": "[JimengAI] Failed to check status for {tid}: {e}", - "err_task_fail_msg": "[JimengAI] Task {tid} failed: {msg}", - "err_batch_fail_all": "[JimengAI] Batch failed: No tasks succeeded.", - "err_copy_fail": "[JimengAI] Failed to copy file: {path}. Error: {e}", - "err_convert_tensor": "[JimengAI] Failed to convert frame to tensor: {e}", - "err_check_status_batch": "[JimengAI] API Error checking batch status: {e}", - "download_retry": "[JimengAI] Warning: Download failed (Attempt {attempt}/{total}). Retrying in {delay}s... Error: {e}", - "stream_recv_image": "[JimengAI] Streaming: Image {index} generated, downloading in background...", - "stream_partial_fail": "[JimengAI] Streaming Warning: Image {index} failed: {msg}", - "popup_req_failed": "[JimengAI] Request failed: {msg}", - "popup_task_failed": "[JimengAI] Task {task_id} failed: {msg}", - "popup_batch_pending": "[JimengAI] Batch ({count} tasks) is pending. Run again to check results.", - "popup_task_pending": "[JimengAI] Task {task_id} is {status}. Run again to check results.", - "popup_param_not_allowed": "[JimengAI] Parameter Error: Parameter '--{param}' is not allowed in the prompt. Please use the node's widget for this value.", - "popup_first_frame_missing": "[JimengAI] Parameter Error: A first frame image must be provided when using a last frame image.", - "popup_ref_missing": "[JimengAI] Parameter Error: At least one reference image must be provided.", - "popup_prepare_failed": "[JimengAI] Failed to prepare task: {e}", - "err_pixels_range": "[JimengAI] Parameter Error: Total pixels must be between {min} ({min_desc}) and {max} ({max_desc}). Your current: {current}", - "err_aspect_ratio": "[JimengAI] Parameter Error: Aspect ratio must be between {min} and {max}. Your current: {current}", - "err_download_img": "[JimengAI] Error: Failed to download the generated image.", - "err_gen_model": "[JimengAI] Failed to generate image with model {model}: {e}", - "err_img_limit_10": "[JimengAI] Parameter Error: The number of input images cannot exceed 10.", - "err_img_limit_15": "[JimengAI] Parameter Error: The sum of input images ({n}) and max generated images ({max}) cannot exceed 15.", - "err_img_limit_group_15": "[JimengAI] Parameter Error: The sum of input images ({n}) and max generated images ({max}) cannot exceed 15 in group mode (Total: {total}).", - "combo_no_keys": "No Keys Found (Check api_keys.json)", - "popup_key_valid_err": "[JimengAI] Config Error: Selected key '{key}' is invalid or not found. Please check api_keys.json.", + "task_finished_single": "Task completed successfully.", + "batch_finished_stats": "Batch finished. Success: {success}, Failed: {failed}.", + "batch_handling": "Handling {count} successful tasks. Sorting by seed and downloading...", + "batch_copying": "Copying files to output directory: {path}", + "err_download_url": "Async download failed, URL: {url}, Error: {e}", + "err_task_create": "Task creation failed: {e}", + "err_task_check": "Failed to check status for {tid}: {e}", + "err_task_fail_msg": "Task {tid} failed: {msg}", + "err_batch_fail_all": "Batch failed: No tasks succeeded.", + "err_copy_fail": "Failed to copy file: {path}. Error: {e}", + "err_convert_tensor": "Failed to convert frame to tensor: {e}", + "err_check_status_batch": "API Error checking batch status: {e}", + "download_retry": "Warning: Download failed (Attempt {attempt}/{total}). Retrying in {delay}s... Error: {e}", + "stream_recv_image": "Streaming: Image {index} generated, downloading in background...", + "stream_partial_fail": "Streaming Warning: Image {index} failed: {msg}", + "popup_req_failed": "Request failed: {msg}", + "popup_task_failed": "Task {task_id} failed: {msg}", + "popup_batch_pending": "Batch ({count} tasks) is pending. Run again to check results.", + "popup_task_pending": "Task {task_id} is {status}. Run again to check results.", + "popup_param_not_allowed": "Parameter Error: Parameter '--{param}' is not allowed in the prompt. Please use the node's widget for this value.", + "popup_first_frame_missing": "Parameter Error: A first frame image must be provided when using a last frame image.", + "popup_ref_missing": "Parameter Error: At least one reference image must be provided.", + "popup_prepare_failed": "Failed to prepare task: {e}", + "err_pixels_range": "Parameter Error: Total pixels must be between {min} ({min_desc}) and {max} ({max_desc}). Your current: {current}", + "err_aspect_ratio": "Parameter Error: Aspect ratio must be between {min} and {max}. Your current: {current}", + "err_download_img": "Error: Failed to download the generated image.", + "err_gen_model": "Failed to generate image with model {model}: {e}", + "err_img_limit_10": "Parameter Error: The number of input images cannot exceed 10.", + "err_img_limit_15": "Parameter Error: The sum of input images ({n}) and max generated images ({max}) cannot exceed 15.", + "err_img_limit_group_15": "Parameter Error: The sum of input images ({n}) and max generated images ({max}) cannot exceed 15 in group mode (Total: {total}).", + "popup_key_valid_err": "Config Error: Selected key '{key}' is invalid or not found. Please check api_keys.json.", + "err_new_key_empty": "Config Error: Manual entry enabled but API Key is empty.", + "err_new_key_invalid": "Auth Failed: Input API Key is invalid. Connection rejected by server.", + "info_new_key_saved": "Info: New key '{name}' verified and saved to api_keys.json.", "api_errors": { "AuthenticationError": "Invalid API Key (401). Please check api_keys.json.", "AccessDenied": "Access Denied (403). No permission or IP whitelist issue.", diff --git a/nodes/nodes_shared.py b/nodes/nodes_shared.py index 1aafbb3..ebaf501 100644 --- a/nodes/nodes_shared.py +++ b/nodes/nodes_shared.py @@ -7,6 +7,7 @@ import re import numpy import PIL.Image import torch +import requests from volcenginesdkarkruntime import Ark from comfy_api.latest import io as comfy_io @@ -15,6 +16,33 @@ import logging from .constants import LOG_TRANSLATIONS, ERROR_TEXT_MATCH_RULES +LOG_PREFIX = "[JimengAI] " + +def patch_log_translations(): + """ + 自动为日志消息添加前缀。 + """ + ignore_keys = {"api_errors"} + + for lang in LOG_TRANSLATIONS: + trans_map = LOG_TRANSLATIONS[lang] + for key, value in trans_map.items(): + if key in ignore_keys or key.startswith("est_"): + continue + + if isinstance(value, str): + if value.strip().startswith("-"): + continue + + if value.startswith("\n"): + if LOG_PREFIX.strip() not in value: + trans_map[key] = "\n" + LOG_PREFIX + value[1:] + else: + if not value.startswith(LOG_PREFIX): + trans_map[key] = LOG_PREFIX + value + +patch_log_translations() + logger = logging.getLogger("JimengAI") if not logger.handlers: handler = logging.StreamHandler() @@ -48,13 +76,19 @@ def detect_system_language(): return "en" -def get_text(key): +def get_text(key, **kwargs): """ 获取指定 key 的本地化文本。 """ global CURRENT_LANG mapping = LOG_TRANSLATIONS.get(CURRENT_LANG, LOG_TRANSLATIONS["en"]) - return mapping.get(key, LOG_TRANSLATIONS["en"].get(key, key)) + msg = mapping.get(key, LOG_TRANSLATIONS["en"].get(key, key)) + if kwargs: + try: + return msg.format(**kwargs) + except: + pass + return msg def log_msg(key, default_msg="", **kwargs): @@ -139,22 +173,67 @@ def load_api_keys(): CURRENT_LANG = detect_system_language() if not os.path.exists(API_KEYS_FILE): - log_msg("api_file_not_found") - return + pass try: - with open(API_KEYS_FILE, "r", encoding="utf-8") as f: - keys_data = json.load(f) - if isinstance(keys_data, list): - for item in keys_data: - if "customName" in item and "apiKey" in item: - API_KEYS_CONFIG.append(item) - if not API_KEYS_CONFIG: - log_msg("api_file_empty") + if os.path.exists(API_KEYS_FILE): + with open(API_KEYS_FILE, "r", encoding="utf-8") as f: + keys_data = json.load(f) + if isinstance(keys_data, list): + for item in keys_data: + if "customName" in item and "apiKey" in item: + API_KEYS_CONFIG.append(item) except Exception as e: log_msg("api_load_error", e=e) +def save_api_key(name, key): + """ + 保存新的 API Key 到配置文件。 + """ + global API_KEYS_CONFIG + + updated = False + for item in API_KEYS_CONFIG: + if item["customName"] == name: + item["apiKey"] = key + updated = True + break + + if not updated: + API_KEYS_CONFIG.append({"customName": name, "apiKey": key}) + + try: + with open(API_KEYS_FILE, "w", encoding="utf-8") as f: + json.dump(API_KEYS_CONFIG, f, indent=2, ensure_ascii=False) + logger.info(f"Saved API Key: {name}") + except Exception as e: + logger.error(f"Failed to save API key: {e}") + + +def validate_api_key(api_key: str) -> bool: + """ + 验证 API Key 是否有效。 + """ + try: + url = "https://ark.cn-beijing.volces.com/api/v3" + headers = { + "Authorization": f"Bearer {api_key}", + "Content-Type": "application/json" + } + + response = requests.get(url, headers=headers, timeout=10) + + if response.status_code == 401: + return False + + return True + + except Exception as e: + logger.error(f"API Key validation error: {e}") + return False + + def _tensor2images(tensor: torch.Tensor) -> list: """ 将 PyTorch Tensor 转换为 PIL Image 列表。 @@ -202,27 +281,44 @@ class JimengAPIClient(comfy_io.ComfyNode): def define_schema(cls) -> comfy_io.Schema: load_api_keys() key_names = [key["customName"] for key in API_KEYS_CONFIG] - if not key_names: - key_names = [get_text("combo_no_keys")] + key_names.append("Custom") return comfy_io.Schema( node_id="JimengAPIClient", display_name="Jimeng API Client", category=GLOBAL_CATEGORY, - inputs=[comfy_io.Combo.Input("key_name", options=key_names)], + inputs=[ + comfy_io.String.Input("new_api_key", default=""), + comfy_io.String.Input("new_key_name", default=""), + comfy_io.Combo.Input("key_name", options=key_names), + ], outputs=[JimengClientType.Output(display_name="client")], ) @classmethod - def execute(cls, key_name) -> comfy_io.NodeOutput: + def execute( + cls, key_name, new_api_key="", new_key_name="" + ) -> comfy_io.NodeOutput: api_key = None - if key_name == get_text("combo_no_keys"): - raise JimengException(get_text("api_file_not_found")) - for key_info in API_KEYS_CONFIG: - if key_info["customName"] == key_name: - api_key = key_info["apiKey"] - break + if key_name == "Custom": + if not new_api_key or not new_api_key.strip(): + raise JimengException(get_text("err_new_key_empty")) + + api_key = new_api_key.strip() + + if not validate_api_key(api_key): + raise JimengException(get_text("err_new_key_invalid")) + + if new_key_name and new_key_name.strip(): + save_api_key(new_key_name.strip(), api_key) + print(get_text("info_new_key_saved", name=new_key_name.strip())) + + else: + for key_info in API_KEYS_CONFIG: + if key_info["customName"] == key_name: + api_key = key_info["apiKey"] + break if not api_key: log_msg("api_key_not_found", key_name=key_name) diff --git a/nodes/nodes_video.py b/nodes/nodes_video.py index 37e953c..a15d882 100644 --- a/nodes/nodes_video.py +++ b/nodes/nodes_video.py @@ -127,6 +127,7 @@ class JimengVideoBase: 异步处理批量任务成功的结果。 下载视频和首尾帧,并整理输出。 """ + # t_start = time.time() if generation_count > 1: log_msg("batch_handling", count=len(successful_tasks)) @@ -222,6 +223,9 @@ class JimengVideoBase: if save_last_frame_batch and f_path: save_to_output(f_path, filename_prefix) + # t_end = time.time() + # print(f"[JimengAI Debug] Batch handling finished in {t_end - t_start:.2f}s") + return comfy_io.NodeOutput( first_video, first_frame, json.dumps(all_responses, indent=2) ) @@ -296,9 +300,7 @@ class JimengVideoBase: ) ret_results = None - async with aiohttp.ClientSession( - connector=aiohttp.TCPConnector(force_close=True) - ) as session: + async with aiohttp.ClientSession() as session: ret_results = await self._handle_batch_success_async( successful_tasks, filename_prefix, diff --git a/nodes/utils_download.py b/nodes/utils_download.py index e5e0e63..efacb71 100644 --- a/nodes/utils_download.py +++ b/nodes/utils_download.py @@ -1,5 +1,6 @@ import os import io +import time import asyncio import aiohttp import torch @@ -26,9 +27,13 @@ async def _fetch_data_from_url_async( for attempt in range(1, retries + 2): try: client_timeout = aiohttp.ClientTimeout(total=timeout) + # t0 = time.time() async with session.get(url, timeout=client_timeout) as response: response.raise_for_status() - return await response.read() + data = await response.read() + # t1 = time.time() + # print(f"[JimengAI Debug] Downloaded {len(data)} bytes from {url} in {t1 - t0:.2f}s") + return data except (aiohttp.ClientError, asyncio.TimeoutError) as e: if attempt > retries: raise e @@ -93,15 +98,58 @@ async def _download_to_temp_base( final_path = os.path.join(full_output_folder, final_filename) try: + # t0 = time.time() data = await _fetch_data_from_url_async(session, url) + # t1 = time.time() with open(final_path, "wb") as f: f.write(data) + # t2 = time.time() + # print(f"[JimengAI Debug] Saved to {final_path}. Fetch: {t1 - t0:.2f}s, Write: {t2 - t1:.2f}s") return (final_path, data) except Exception as e: log_msg("err_download_url", url=url, e=e) return (None, None) +async def _download_to_file_stream_async( + session: aiohttp.ClientSession, + url: str, + file_path: str, + timeout: int = DEFAULT_DOWNLOAD_TIMEOUT, + retries: int = DEFAULT_DOWNLOAD_RETRIES, +) -> bool: + """ + 流式下载并写入文件 + """ + for attempt in range(1, retries + 2): + try: + client_timeout = aiohttp.ClientTimeout(total=timeout) + # t0 = time.time() + async with session.get(url, timeout=client_timeout) as response: + response.raise_for_status() + with open(file_path, "wb") as f: + while True: + chunk = await response.content.read(1024 * 1024) # 1MB chunk + if not chunk: + break + f.write(chunk) + # t1 = time.time() + # print(f"[JimengAI Debug] Stream downloaded to {file_path} in {t1 - t0:.2f}s") + return True + except (aiohttp.ClientError, asyncio.TimeoutError) as e: + if attempt > retries: + raise e + retry_delay = 2 + log_msg( + "download_retry", + attempt=attempt, + total=retries + 1, + delay=retry_delay, + e=e, + ) + await asyncio.sleep(retry_delay) + return False + async def download_video_to_temp( session: aiohttp.ClientSession, url: str, @@ -115,10 +163,30 @@ async def download_video_to_temp( if not url: return None file_ext = url.split(".")[-1].split("?")[0] or "mp4" - (path, _) = await _download_to_temp_base( - session, url, prefix, seed, save_path_name, file_ext + + if seed is not None: + prefix = f"{prefix}_seed_{seed}" + + output_dir = folder_paths.get_temp_directory() + if save_path_name: + output_dir = os.path.join(output_dir, save_path_name) + + (full_output_folder, filename, _, _, _) = folder_paths.get_save_image_path( + prefix, output_dir ) - return path + os.makedirs(full_output_folder, exist_ok=True) + + final_filename = f"{filename}_{random.randint(1, 10000)}.{file_ext}" + final_path = os.path.join(full_output_folder, final_filename) + + try: + success = await _download_to_file_stream_async(session, url, final_path) + if success: + return final_path + return None + except Exception as e: + log_msg("err_download_url", url=url, e=e) + return None async def download_image_to_temp( diff --git a/pyproject.toml b/pyproject.toml index 82816f0..d4e5cf9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "ComfyUI-Jimeng-API" description = "在 ComfyUI 中使用火山方舟API提供的即梦(豆包)Seedream 和 Seedance 模型。 / Using the Volcano Ark API to utilize the Seedream and Seedance models of Jimeng (Doubao) in ComfyUI." -version = "2.1.4" +version = "2.1.5" license = {file = "LICENSE"} dependencies = ["volcengine-python-sdk[ark]>=5.0.6"] diff --git a/web/docs/JimengAPIClient/zh.md b/web/docs/JimengAPIClient/zh.md index 27655c9..f413254 100644 --- a/web/docs/JimengAPIClient/zh.md +++ b/web/docs/JimengAPIClient/zh.md @@ -8,7 +8,9 @@ | 参数名 | 类型 | 必填 | 默认值 | 描述 | | :--- | :--- | :--- | :--- | :--- | -| `key_name` | `COMBO` | 是 | - | 从 `api_keys.json` 中选择 API 密钥配置名称。 | +| `key_name` | `COMBO` | 是 | - | 从 `api_keys.json` 中选择 API 密钥配置名称,或选择 `Custom` 以手动输入。 | +| `new_api_key` | `STRING` | 否 | - | 当 `key_name` 选为 `Custom` 时显示。手动输入的 API Key。 | +| `new_key_name` | `STRING` | 否 | - | 当 `key_name` 选为 `Custom` 时显示。若填写此项,Key 将被保存到 `api_keys.json`(需刷新页面生效)。 | #### 输出 (Outputs) diff --git a/web/js/jimeng_dynamic_widgets.js b/web/js/jimeng_dynamic_widgets.js index b5029a5..a906aa9 100644 --- a/web/js/jimeng_dynamic_widgets.js +++ b/web/js/jimeng_dynamic_widgets.js @@ -12,7 +12,8 @@ const TARGET_WIDGETS = [ 'enable_random_seed', 'auto_duration', 'draft_mode', - 'reuse_last_draft_task' + 'reuse_last_draft_task', + 'key_name' ]; /** @@ -269,6 +270,20 @@ function widgetLogic(node, widget) { } } + // 处理 API Client 节点逻辑 + if (node.comfyClass === "JimengAPIClient") { + if (widget.name === 'key_name') { + const isCustom = widget.value === "Custom"; + const newKeyWidget = findWidgetByName(node, 'new_api_key'); + const newNameWidget = findWidgetByName(node, 'new_key_name'); + + const changedKey = toggleWidget(node, newKeyWidget, isCustom); + const changedName = toggleWidget(node, newNameWidget, isCustom); + + if (changedKey || changedName) shouldResize = true; + } + } + // 2. 若检测到布局实质变更,应用新尺寸并恢复高度差 const paddingChanged = applyBottomPadding(node);