原来每个方向各按自己的内容裁剪,8 个方向出 8 种尺寸,角色在各自 画面里的位置也不一致,游戏里切换朝向会跳。人工做法是一帧一帧手动 对位置,这里把它自动化。 新增三个参数: - align_mode 锚点对齐·统一画布(默认) - anchor_type 脚底中心(默认)/ 包围盒底边中心 / 包围盒中心 - align_scope 逐帧对齐·脚底钉死(默认)/ 按方向统一平移 锚点为什么取「脚底中心」:角色站在地面上,脚底才是它在世界里的位置; 而斗篷、披风、手杖会把包围盒拽向一侧。故 y 取最低的不透明行, x 取底部窄带的水平质心 —— 那些外挂物基本不会垂到脚底,走路时两脚 一前一后,窄带质心正好落在两脚之间,即人真正站立的点。 画布尺寸由「所有方向、所有帧相对各自锚点的最大延展」求并集得出, 因此既统一又不会切到任何一帧。 实测(97 帧真实素材): 不对齐 8 种尺寸 各方向锚点散布 x 48.9px / y 27px 按方向统一平移 统一267x372 x 7.1px / y 4px,跨帧位移 13~23px(保留摆动) 逐帧对齐 统一284x367 x 0.76px / y 0px,跨帧位移约 1px 默认取逐帧对齐:行走循环本就该原地播放、位移交给游戏代码,sprite 内部不该有整体漂移,而 AI 生成的视频往往有(实测达 22px)。 info 输出新增统一画布尺寸、锚点坐标与 Unity/Godot 归一化 pivot (左下为原点),照着填进引擎 8 个方向即可共用同一套坐标。 两个示例工作流同步更新 widgets(13→16,不同步会参数错位), 并已校验 widget 数量与结构自洽性。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1166 lines
22 KiB
JSON
1166 lines
22 KiB
JSON
{
|
||
"id": "5f8c3d21-7b94-4e06-a1d8-9c2e4b7f350a",
|
||
"revision": 0,
|
||
"last_node_id": 20,
|
||
"last_link_id": 19,
|
||
"nodes": [
|
||
{
|
||
"id": 1,
|
||
"type": "VHS_LoadVideo",
|
||
"pos": [
|
||
-2680,
|
||
340
|
||
],
|
||
"size": [
|
||
340,
|
||
480
|
||
],
|
||
"flags": {},
|
||
"order": 0,
|
||
"mode": 0,
|
||
"inputs": [],
|
||
"outputs": [
|
||
{
|
||
"name": "IMAGE",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
1,
|
||
2
|
||
]
|
||
},
|
||
{
|
||
"name": "frame_count",
|
||
"type": "INT",
|
||
"links": []
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"links": []
|
||
},
|
||
{
|
||
"name": "video_info",
|
||
"type": "VHS_VIDEOINFO",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_LoadVideo"
|
||
},
|
||
"widgets_values": {
|
||
"video": "八方向行走.mp4",
|
||
"force_rate": 24,
|
||
"custom_width": 0,
|
||
"custom_height": 0,
|
||
"frame_load_cap": 0,
|
||
"skip_first_frames": 0,
|
||
"select_every_nth": 1
|
||
},
|
||
"color": "#232",
|
||
"bgcolor": "#353",
|
||
"title": "① 加载视频(force_rate 设帧率)"
|
||
},
|
||
{
|
||
"id": 2,
|
||
"type": "RuiLucida",
|
||
"pos": [
|
||
-2270,
|
||
340
|
||
],
|
||
"size": [
|
||
340,
|
||
250
|
||
],
|
||
"flags": {},
|
||
"order": 1,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "image",
|
||
"type": "IMAGE",
|
||
"link": 1
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "alpha",
|
||
"type": "MASK",
|
||
"links": [
|
||
3
|
||
]
|
||
},
|
||
{
|
||
"name": "cutout",
|
||
"type": "IMAGE",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"aux_id": "rui40000/Ruinode",
|
||
"Node name for S&R": "RuiLucida"
|
||
},
|
||
"widgets_values": [
|
||
"lucida.safetensors",
|
||
"fp16",
|
||
"auto",
|
||
0.5,
|
||
1.0,
|
||
false,
|
||
false
|
||
],
|
||
"color": "#232",
|
||
"bgcolor": "#353",
|
||
"title": "② Lucida 抠图(一次抠整张,8 个角色都能识别)"
|
||
},
|
||
{
|
||
"id": 3,
|
||
"type": "RuiEightDirSplit",
|
||
"pos": [
|
||
-1860,
|
||
340
|
||
],
|
||
"size": [
|
||
380,
|
||
400
|
||
],
|
||
"flags": {},
|
||
"order": 2,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 2
|
||
},
|
||
{
|
||
"name": "masks",
|
||
"type": "MASK",
|
||
"link": 3
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "dir_1",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
4,
|
||
5
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_2",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
6,
|
||
7
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_3",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
8,
|
||
9
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_4",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
10,
|
||
11
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_5",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
12,
|
||
13
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_6",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
14,
|
||
15
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_7",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
16,
|
||
17
|
||
]
|
||
},
|
||
{
|
||
"name": "dir_8",
|
||
"type": "IMAGE",
|
||
"links": [
|
||
18,
|
||
19
|
||
]
|
||
},
|
||
{
|
||
"name": "info",
|
||
"type": "STRING",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"aux_id": "rui40000/Ruinode",
|
||
"Node name for S&R": "RuiEightDirSplit"
|
||
},
|
||
"widgets_values": [
|
||
3,
|
||
3,
|
||
"4",
|
||
"SW,S,SE,W,E,NW,N,NE",
|
||
"已带透明通道(推荐·上游接抠图节点)",
|
||
0.92,
|
||
0.2,
|
||
1.0,
|
||
1.0,
|
||
0.05,
|
||
true,
|
||
"锚点对齐·统一画布(做游戏必选)",
|
||
"脚底中心(推荐)",
|
||
"逐帧对齐·脚底钉死(推荐)",
|
||
true,
|
||
16
|
||
],
|
||
"color": "#232",
|
||
"bgcolor": "#353",
|
||
"title": "③ 八方向拆分(拆分+编号+分组)"
|
||
},
|
||
{
|
||
"id": 4,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
-160
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 3,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 4
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/1_SW",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"color": "#232",
|
||
"bgcolor": "#353",
|
||
"title": "1. SW → 透明 webm"
|
||
},
|
||
{
|
||
"id": 5,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
-160
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 4,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 5
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/1_SW/SW"
|
||
],
|
||
"title": "1. SW → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 6,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
170
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 5,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 6
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/2_S",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "2. S → 透明 webm"
|
||
},
|
||
{
|
||
"id": 7,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
170
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 6,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 7
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/2_S/S"
|
||
],
|
||
"title": "2. S → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 8,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
500
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 7,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 8
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/3_SE",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "3. SE → 透明 webm"
|
||
},
|
||
{
|
||
"id": 9,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
500
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 8,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 9
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/3_SE/SE"
|
||
],
|
||
"title": "3. SE → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 10,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
830
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 9,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 10
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/4_W",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "4. W → 透明 webm"
|
||
},
|
||
{
|
||
"id": 11,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
830
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 10,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 11
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/4_W/W"
|
||
],
|
||
"title": "4. W → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 12,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
1160
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 11,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 12
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/5_E",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "5. E → 透明 webm"
|
||
},
|
||
{
|
||
"id": 13,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
1160
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 12,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 13
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/5_E/E"
|
||
],
|
||
"title": "5. E → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 14,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
1490
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 13,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 14
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/6_NW",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "6. NW → 透明 webm"
|
||
},
|
||
{
|
||
"id": 15,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
1490
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 14,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 15
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/6_NW/NW"
|
||
],
|
||
"title": "6. NW → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 16,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
1820
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 15,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 16
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/7_N",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "7. N → 透明 webm"
|
||
},
|
||
{
|
||
"id": 17,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
1820
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 16,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 17
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/7_N/N"
|
||
],
|
||
"title": "7. N → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 18,
|
||
"type": "VHS_VideoCombine",
|
||
"pos": [
|
||
-1400,
|
||
2150
|
||
],
|
||
"size": [
|
||
320,
|
||
460
|
||
],
|
||
"flags": {},
|
||
"order": 17,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 18
|
||
},
|
||
{
|
||
"name": "audio",
|
||
"type": "AUDIO",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "meta_batch",
|
||
"type": "VHS_BatchManager",
|
||
"link": null
|
||
},
|
||
{
|
||
"name": "vae",
|
||
"type": "VAE",
|
||
"link": null
|
||
}
|
||
],
|
||
"outputs": [
|
||
{
|
||
"name": "Filenames",
|
||
"type": "VHS_FILENAMES",
|
||
"links": []
|
||
}
|
||
],
|
||
"properties": {
|
||
"Node name for S&R": "VHS_VideoCombine"
|
||
},
|
||
"widgets_values": {
|
||
"frame_rate": 24,
|
||
"loop_count": 0,
|
||
"filename_prefix": "8dir/8_NE",
|
||
"format": "video/webm",
|
||
"pix_fmt": "yuva420p",
|
||
"crf": 20,
|
||
"save_metadata": true,
|
||
"trim_to_audio": false,
|
||
"pingpong": false,
|
||
"save_output": true
|
||
},
|
||
"title": "8. NE → 透明 webm"
|
||
},
|
||
{
|
||
"id": 19,
|
||
"type": "SaveImage",
|
||
"pos": [
|
||
-1040,
|
||
2150
|
||
],
|
||
"size": [
|
||
300,
|
||
300
|
||
],
|
||
"flags": {},
|
||
"order": 18,
|
||
"mode": 0,
|
||
"inputs": [
|
||
{
|
||
"name": "images",
|
||
"type": "IMAGE",
|
||
"link": 19
|
||
}
|
||
],
|
||
"outputs": [],
|
||
"properties": {
|
||
"cnr_id": "comfy-core",
|
||
"ver": "0.3.49",
|
||
"Node name for S&R": "SaveImage"
|
||
},
|
||
"widgets_values": [
|
||
"8dir_frames/8_NE/NE"
|
||
],
|
||
"title": "8. NE → 透明 PNG 序列帧"
|
||
},
|
||
{
|
||
"id": 20,
|
||
"type": "Note",
|
||
"pos": [
|
||
-2680,
|
||
880
|
||
],
|
||
"size": [
|
||
740,
|
||
1120
|
||
],
|
||
"flags": {},
|
||
"order": 19,
|
||
"mode": 0,
|
||
"inputs": [],
|
||
"outputs": [],
|
||
"properties": {},
|
||
"widgets_values": [
|
||
"八方向行走动画 —— 完整管线\n\n【前置步骤(在本工作流之外完成)】\n 角色图 →(GPTimage2)→ 八方向静态图 →(Seedance 首尾帧)→ 循环行走视频\n 视频每一帧上都排布着 8 个朝向的角色。\n\n【本工作流做的事】\n ① VHS「Load Video」把视频转成序列帧\n · force_rate 就是帧率选择。设 0 用源视频帧率;\n 设 12 可减半出帧、素材更小,走路动画通常 8~12 帧一循环就够\n · frame_load_cap 可限制总帧数,先小批量试参数很有用\n ② Lucida 抠图,为拆分提供语义级 alpha(见下方「为什么要接抠图节点」)\n ③ 八方向拆分:切格 + 编号 + 按方向分组,一次给出 8 条序列\n ④ 每个方向各接一个 VHS「Video Combine」出透明 webm\n ⑤ 每个方向各接一个 SaveImage 出透明 PNG 序列帧\n\n■ 为什么要接抠图节点,而不是让拆分节点自己扣白底 ————\n\n拆分节点自带的「白底转透明」是纯颜色阈值法:按「离白色多远」估 alpha。\n它的死穴是角色身上的白色衣物 —— 白衬衫本身就接近白,alpha 天生偏低,\n一旦收边压白边,衬衫就会被啃出破洞(实测会看到背景色透过衣服)。\n\nLucida 是按语义判断的,知道那是衣服而不是背景。实测(同一素材、\n同等白边水平):主体被啃掉的面积比阈值法少 35%,白衬衫完好。\nLucida 一次就能把整张雪碧图的 8 个角色全部识别出来\n(各格前景占比 0.18~0.24,中间空格 0.002)。\n\n素材里确实没有白色元素时,可以把 bg_mode 改成「白底转透明」省掉模型开销;\n此时 edge_shrink 要调到 0.35 以上才压得住白边。\n\n■ 治白边的两个参数 ————————————————————\n\n · edge_shrink(主力)把边缘那圈几乎全是背景的半透明像素收掉。\n 配模型 alpha 用 0.15~0.25;配阈值法要 0.35+。\n 实测:0 → 白边强度 0.048;0.2 → 0.026;0.5 → 0.016。\n · decontaminate(辅助)颜色反溢出,按\n 观察色 = 前景×a + 白×(1-a) 反解真正的前景色。\n 单独用改善很小(约 3%),要和收边配合。\n\n\n■ 尺寸统一与锚点对齐(做游戏的关键)——————————\n\n 不开对齐时,8 个方向各按自己的内容裁剪,尺寸互不相同\n (实测 8 个方向出了 8 种尺寸),角色在各自画面里的位置也不一致\n ——游戏里切换朝向时角色会跳一下。\n\n · align_mode = 锚点对齐·统一画布\n 所有方向输出同一尺寸,锚点落在画布同一位置。\n 实测各方向锚点散布:x 48.9px → 0.76px,y 27px → 0px。\n · anchor_type = 脚底中心\n y 取最低的不透明行,x 取底部窄带的水平质心。\n x 不用包围盒中心,是因为斗篷、披风、手杖会把包围盒拽向一侧,\n 而它们基本不会垂到脚底。走路时两脚一前一后,窄带质心正好\n 落在两脚之间,也就是人真正站立的点。\n · align_scope = 逐帧对齐·脚底钉死\n 等价于人工「一帧一帧对位置」。行走循环本就该原地播放、\n 位移交给游戏代码,sprite 内部不该有整体漂移;AI 生成的视频\n 往往有(实测同方向跨帧漂移 22px),此模式能压到 1px。\n 若角色本就该有前后摆动(挥剑、跳跃),改用「按方向统一平移」。\n\n ⚠ info 输出里会给出统一画布尺寸、锚点坐标,以及 Unity/Godot 的\n 归一化 pivot(左下为原点)。把那个 pivot 填进引擎的 Sprite 设置,\n 8 个方向就能共用同一套坐标,切换朝向纹丝不动。\n\n■ 拆分节点的其他关键参数 ————————————————\n\n · grid_cols / grid_rows / empty_cells\n 3×3 中间留空即 empty_cells=4。序号行优先、从 0 开始。\n · direction_names\n 按「跳过空格后的先后顺序」命名,默认对应:\n SW S SE ← 行1:面向观众\n W E ← 行2:侧面\n NW N NE ← 行3:背对观众\n 与素材不符就直接改这行,名字只影响标注不影响画面。\n · expand_beyond_cell(务必开启)\n 允许角色超出格子边界。关闭时按格线严格切分,角色只要探出格线\n 就会被切断(最典型的是脚被削掉)。开启后格子只用来判定方向,\n 实际范围由角色自身的连通区域决定。三种 bg_mode 都有效。\n · auto_crop\n 裁剪框取该方向所有帧的并集,因此整条序列尺寸一致(能合成视频),\n 角色也不会在帧间跳动。\n\n■ webm 透明的关键 ————————————————————\n\n Video Combine 的 format 必须选 video/webm,pix_fmt 必须选 yuva420p。\n 注意:alpha 存放在 WebM 的独立边带里,用 ffprobe 看主流会显示 yuv420p,\n 这是正常的。播放器/引擎(走 libvpx 解码)能正确读到透明通道;\n 若要用 ffmpeg 自行验证,需显式加 -c:v libvpx-vp9 解码,\n 否则内置 vp9 解码器不输出 alpha,会让人误以为透明丢了。"
|
||
],
|
||
"color": "#432",
|
||
"bgcolor": "#653"
|
||
}
|
||
],
|
||
"links": [
|
||
[
|
||
1,
|
||
1,
|
||
0,
|
||
2,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
2,
|
||
1,
|
||
0,
|
||
3,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
3,
|
||
2,
|
||
0,
|
||
3,
|
||
1,
|
||
"MASK"
|
||
],
|
||
[
|
||
4,
|
||
3,
|
||
0,
|
||
4,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
5,
|
||
3,
|
||
0,
|
||
5,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
6,
|
||
3,
|
||
1,
|
||
6,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
7,
|
||
3,
|
||
1,
|
||
7,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
8,
|
||
3,
|
||
2,
|
||
8,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
9,
|
||
3,
|
||
2,
|
||
9,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
10,
|
||
3,
|
||
3,
|
||
10,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
11,
|
||
3,
|
||
3,
|
||
11,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
12,
|
||
3,
|
||
4,
|
||
12,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
13,
|
||
3,
|
||
4,
|
||
13,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
14,
|
||
3,
|
||
5,
|
||
14,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
15,
|
||
3,
|
||
5,
|
||
15,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
16,
|
||
3,
|
||
6,
|
||
16,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
17,
|
||
3,
|
||
6,
|
||
17,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
18,
|
||
3,
|
||
7,
|
||
18,
|
||
0,
|
||
"IMAGE"
|
||
],
|
||
[
|
||
19,
|
||
3,
|
||
7,
|
||
19,
|
||
0,
|
||
"IMAGE"
|
||
]
|
||
],
|
||
"groups": [],
|
||
"config": {},
|
||
"extra": {
|
||
"ds": {
|
||
"scale": 0.5,
|
||
"offset": [
|
||
2820,
|
||
100
|
||
]
|
||
}
|
||
},
|
||
"version": 0.4
|
||
} |