Compare commits

...
Author SHA1 Message Date
ausboss a4d0b18920 Pika H3 Flex: Fast test opens plainly off, and examples can't ship a half-set switch
The Fast test row set the video loader to 1 MP when off, but the workflow ships the loader at 0.41 MP, so the row opened striped 'changed' with neither side picked. Its off side is now 0.41.

workflow_contract now fails any Workflow Switches row whose saved values sit on neither side, are half on and half off, or disagree with whether its nodes run.
2026-11-05 01:51:48 +00:00
ausboss bd8ead7ef9 Pika H3 Flex: show how to dress the person in your video, and name the video by what it is
- Recipes: copy-moves recipes say Picture 1 is your person; new recipe for a hat or outfit on the person in your video.
- Your pictures: Picture 1 opens as person, change its job for a place, a hat or a thing.
- Settings: steps for a clip from pictures and for a new hat or outfit, beside the swap steps.
- Video loader, switch and callout: 'Your clip' instead of 'Swap or copy moves'.
- H3 Prompt Writer: with only an outfit or thing picture and a swap or copy-moves video, the error says to load a still of the video's person as Picture 1.
2026-11-05 01:16:45 +00:00
ausboss 3fd491c839 Pika H3 Flex: preview picture, a frame from a clip the workflow made 2026-11-04 10:11:32 -06:00
ausboss 93bf3dc325 Pika H3 Flex: the swap steps set the video job; drop the unfilled version line 2026-11-04 09:58:18 -06:00
ausboss 5753f4048a Pika H3 Flex: round the clip size to 32 px, which H3 needs, so no band wraps in at the bottom 2026-11-04 09:56:55 -06:00
ausboss 841bfa7d06 Pika H3 Flex: the Settings note covers swapping two people; Voice and Song saved blank 2026-11-04 09:09:52 -06:00
6 changed files with 111 additions and 25 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

+25 -25
View File
@@ -39,10 +39,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"{\"v\": 1, \"title\": \"Pika H3 Flex Video | Swap a Person, Copy Moves, Voice and Song\", \"subtitle\": \"Put your person into a video, or type what happens and give each picture a job. Add a voice or a song when you want one.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"1. Load **Picture 1**.\\n2. **Type what happens**, one line for each thing.\\n3. Pick how many **seconds** on **Seconds**.\\n4. Press **Run**.\\n\\nThat is all you need. Everything else is a switch in **Pictures**, **Video and sound** or **Extras**, and it stays out of the way until you turn it on.\\n\\n**The first run takes longer.** H3, its text encoder and its VAEs come to about 45 GB, and all of it has to load once.\\n\\nEach part of the page has its own note with the details: **Settings**, **pictures**, **recipes**, **video and sound**, and **writing the lines**.\\n\\nYou never have to learn H3's format. H3 Prompt Writer writes it for you, and **Prompt H3 sees** on the right shows what it wrote.\\n\\nPika H3 Flex is by Pika, on MiniMax H3 by MiniMax. These are Comfy-Org's ComfyUI files.\\n\\nNeeds ComfyUI {COMFY_NEEDS} or newer and AusBoss nodes {PACK} or newer (update first).\", \"models\": [{\"name\": \"minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"20.97 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"note\": \"the Ref2VA model, not FL2VA\"}, {\"name\": \"qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"dir\": \"text_encoders\", \"size\": \"15.69 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/text_encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"note\": \"the same file every H3 workflow uses: you may have it already\"}, {\"name\": \"minimax_h3_video_vae_fp16.safetensors\", \"dir\": \"vae\", \"size\": \"5.21 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_fp16.safetensors\", \"note\": \"\"}, {\"name\": \"minimax_h3_audio_vae_fp32.safetensors\", \"dir\": \"vae\", \"size\": \"0.60 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_audio_vae_fp32.safetensors\", \"note\": \"the sound\"}, {\"name\": \"pika_h3_flex_ref2va_v1_bf16.safetensors\", \"dir\": \"loras\", \"size\": \"1.96 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/loras/pika_h3_flex_ref2va_v1_bf16.safetensors\", \"note\": \"Pika's add-on, already in the LoRA Loader\"}, {\"name\": \"minimax_h3_ref2va_pruned_w6a8.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"15.98 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_w6a8.safetensors\", \"note\": \"only for Low VRAM: use it in place of the first file\"}, {\"name\": \"minimax_h3_video_vae_int8_convrot.safetensors\", \"dir\": \"vae\", \"size\": \"2.81 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_int8_convrot.safetensors\", \"note\": \"only for Low VRAM: use it in place of the VAE above\"}, {\"name\": \"qwen3vl_8b_int8_convrot.safetensors\", \"dir\": \"text_encoders\", \"size\": \"9.35 GB\", \"url\": \"https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors\", \"note\": \"only for Auto prompt: the small text model\"}], \"packs\": [{\"name\": \"ComfyUI-AusBoss\", \"url\": \"https://github.com/ausboss/ComfyUI-AusBoss\", \"node\": \"AUSBOSS_NODES_Callout\"}], \"links\": [{\"label\": \"YouTube \u00b7 20 things you can do with an edit model\", \"url\": \"https://youtu.be/GociGWQQDSs\"}, {\"label\": \"YouTube \u00b7 ausbossdev\", \"url\": \"https://www.youtube.com/@ausbossdev\"}, {\"label\": \"Pika H3 Flex \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Pika-Labs/Pika-H3-Flex\"}, {\"label\": \"MiniMax H3 files \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3\"}, {\"label\": \"GitHub \u00b7 ausboss\", \"url\": \"https://github.com/ausboss\"}, {\"label\": \"Civitai \u00b7 AusBoss\", \"url\": \"https://civitai.com/user/AusBoss\"}, {\"label\": \"X \u00b7 Zanzibased\", \"url\": \"https://x.com/Zanzibased\"}]}"
"{\"v\": 1, \"title\": \"Pika H3 Flex Video | Swap a Person, Copy Moves, Voice and Song\", \"subtitle\": \"Put your person into a video, or type what happens and give each picture a job. Add a voice or a song when you want one.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"1. Load **Picture 1**.\\n2. **Type what happens**, one line for each thing.\\n3. Pick how many **seconds** on **Seconds**.\\n4. Press **Run**.\\n\\nThat is all you need. Everything else is a switch in **Pictures**, **Video and sound** or **Extras**, and it stays out of the way until you turn it on.\\n\\n**The first run takes longer.** H3, its text encoder and its VAEs come to about 45 GB, and all of it has to load once.\\n\\nEach part of the page has its own note with the details: **Settings**, **pictures**, **recipes**, **video and sound**, and **writing the lines**.\\n\\nYou never have to learn H3's format. H3 Prompt Writer writes it for you, and **Prompt H3 sees** on the right shows what it wrote.\\n\\nPika H3 Flex is by Pika, on MiniMax H3 by MiniMax. These are Comfy-Org's ComfyUI files.\", \"models\": [{\"name\": \"minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"20.97 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"note\": \"the Ref2VA model, not FL2VA\"}, {\"name\": \"qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"dir\": \"text_encoders\", \"size\": \"15.69 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/text_encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"note\": \"the same file every H3 workflow uses: you may have it already\"}, {\"name\": \"minimax_h3_video_vae_fp16.safetensors\", \"dir\": \"vae\", \"size\": \"5.21 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_fp16.safetensors\", \"note\": \"\"}, {\"name\": \"minimax_h3_audio_vae_fp32.safetensors\", \"dir\": \"vae\", \"size\": \"0.60 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_audio_vae_fp32.safetensors\", \"note\": \"the sound\"}, {\"name\": \"pika_h3_flex_ref2va_v1_bf16.safetensors\", \"dir\": \"loras\", \"size\": \"1.96 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/loras/pika_h3_flex_ref2va_v1_bf16.safetensors\", \"note\": \"Pika's add-on, already in the LoRA Loader\"}, {\"name\": \"minimax_h3_ref2va_pruned_w6a8.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"15.98 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_w6a8.safetensors\", \"note\": \"only for Low VRAM: use it in place of the first file\"}, {\"name\": \"minimax_h3_video_vae_int8_convrot.safetensors\", \"dir\": \"vae\", \"size\": \"2.81 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_int8_convrot.safetensors\", \"note\": \"only for Low VRAM: use it in place of the VAE above\"}, {\"name\": \"qwen3vl_8b_int8_convrot.safetensors\", \"dir\": \"text_encoders\", \"size\": \"9.35 GB\", \"url\": \"https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors\", \"note\": \"only for Auto prompt: the small text model\"}], \"packs\": [{\"name\": \"ComfyUI-AusBoss\", \"url\": \"https://github.com/ausboss/ComfyUI-AusBoss\", \"node\": \"AUSBOSS_NODES_Callout\"}], \"links\": [{\"label\": \"YouTube \u00b7 20 things you can do with an edit model\", \"url\": \"https://youtu.be/GociGWQQDSs\"}, {\"label\": \"YouTube \u00b7 ausbossdev\", \"url\": \"https://www.youtube.com/@ausbossdev\"}, {\"label\": \"Pika H3 Flex \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Pika-Labs/Pika-H3-Flex\"}, {\"label\": \"MiniMax H3 files \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3\"}, {\"label\": \"GitHub \u00b7 ausboss\", \"url\": \"https://github.com/ausboss\"}, {\"label\": \"Civitai \u00b7 AusBoss\", \"url\": \"https://civitai.com/user/AusBoss\"}, {\"label\": \"X \u00b7 Zanzibased\", \"url\": \"https://x.com/Zanzibased\"}]}"
],
"widgets_values_named": {
"note": "{\"v\": 1, \"title\": \"Pika H3 Flex Video | Swap a Person, Copy Moves, Voice and Song\", \"subtitle\": \"Put your person into a video, or type what happens and give each picture a job. Add a voice or a song when you want one.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"1. Load **Picture 1**.\\n2. **Type what happens**, one line for each thing.\\n3. Pick how many **seconds** on **Seconds**.\\n4. Press **Run**.\\n\\nThat is all you need. Everything else is a switch in **Pictures**, **Video and sound** or **Extras**, and it stays out of the way until you turn it on.\\n\\n**The first run takes longer.** H3, its text encoder and its VAEs come to about 45 GB, and all of it has to load once.\\n\\nEach part of the page has its own note with the details: **Settings**, **pictures**, **recipes**, **video and sound**, and **writing the lines**.\\n\\nYou never have to learn H3's format. H3 Prompt Writer writes it for you, and **Prompt H3 sees** on the right shows what it wrote.\\n\\nPika H3 Flex is by Pika, on MiniMax H3 by MiniMax. These are Comfy-Org's ComfyUI files.\\n\\nNeeds ComfyUI {COMFY_NEEDS} or newer and AusBoss nodes {PACK} or newer (update first).\", \"models\": [{\"name\": \"minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"20.97 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"note\": \"the Ref2VA model, not FL2VA\"}, {\"name\": \"qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"dir\": \"text_encoders\", \"size\": \"15.69 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/text_encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"note\": \"the same file every H3 workflow uses: you may have it already\"}, {\"name\": \"minimax_h3_video_vae_fp16.safetensors\", \"dir\": \"vae\", \"size\": \"5.21 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_fp16.safetensors\", \"note\": \"\"}, {\"name\": \"minimax_h3_audio_vae_fp32.safetensors\", \"dir\": \"vae\", \"size\": \"0.60 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_audio_vae_fp32.safetensors\", \"note\": \"the sound\"}, {\"name\": \"pika_h3_flex_ref2va_v1_bf16.safetensors\", \"dir\": \"loras\", \"size\": \"1.96 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/loras/pika_h3_flex_ref2va_v1_bf16.safetensors\", \"note\": \"Pika's add-on, already in the LoRA Loader\"}, {\"name\": \"minimax_h3_ref2va_pruned_w6a8.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"15.98 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_w6a8.safetensors\", \"note\": \"only for Low VRAM: use it in place of the first file\"}, {\"name\": \"minimax_h3_video_vae_int8_convrot.safetensors\", \"dir\": \"vae\", \"size\": \"2.81 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_int8_convrot.safetensors\", \"note\": \"only for Low VRAM: use it in place of the VAE above\"}, {\"name\": \"qwen3vl_8b_int8_convrot.safetensors\", \"dir\": \"text_encoders\", \"size\": \"9.35 GB\", \"url\": \"https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors\", \"note\": \"only for Auto prompt: the small text model\"}], \"packs\": [{\"name\": \"ComfyUI-AusBoss\", \"url\": \"https://github.com/ausboss/ComfyUI-AusBoss\", \"node\": \"AUSBOSS_NODES_Callout\"}], \"links\": [{\"label\": \"YouTube \u00b7 20 things you can do with an edit model\", \"url\": \"https://youtu.be/GociGWQQDSs\"}, {\"label\": \"YouTube \u00b7 ausbossdev\", \"url\": \"https://www.youtube.com/@ausbossdev\"}, {\"label\": \"Pika H3 Flex \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Pika-Labs/Pika-H3-Flex\"}, {\"label\": \"MiniMax H3 files \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3\"}, {\"label\": \"GitHub \u00b7 ausboss\", \"url\": \"https://github.com/ausboss\"}, {\"label\": \"Civitai \u00b7 AusBoss\", \"url\": \"https://civitai.com/user/AusBoss\"}, {\"label\": \"X \u00b7 Zanzibased\", \"url\": \"https://x.com/Zanzibased\"}]}"
"note": "{\"v\": 1, \"title\": \"Pika H3 Flex Video | Swap a Person, Copy Moves, Voice and Song\", \"subtitle\": \"Put your person into a video, or type what happens and give each picture a job. Add a voice or a song when you want one.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"1. Load **Picture 1**.\\n2. **Type what happens**, one line for each thing.\\n3. Pick how many **seconds** on **Seconds**.\\n4. Press **Run**.\\n\\nThat is all you need. Everything else is a switch in **Pictures**, **Video and sound** or **Extras**, and it stays out of the way until you turn it on.\\n\\n**The first run takes longer.** H3, its text encoder and its VAEs come to about 45 GB, and all of it has to load once.\\n\\nEach part of the page has its own note with the details: **Settings**, **pictures**, **recipes**, **video and sound**, and **writing the lines**.\\n\\nYou never have to learn H3's format. H3 Prompt Writer writes it for you, and **Prompt H3 sees** on the right shows what it wrote.\\n\\nPika H3 Flex is by Pika, on MiniMax H3 by MiniMax. These are Comfy-Org's ComfyUI files.\", \"models\": [{\"name\": \"minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"20.97 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_int8_convrot.safetensors\", \"note\": \"the Ref2VA model, not FL2VA\"}, {\"name\": \"qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"dir\": \"text_encoders\", \"size\": \"15.69 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/text_encoders/qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors\", \"note\": \"the same file every H3 workflow uses: you may have it already\"}, {\"name\": \"minimax_h3_video_vae_fp16.safetensors\", \"dir\": \"vae\", \"size\": \"5.21 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_fp16.safetensors\", \"note\": \"\"}, {\"name\": \"minimax_h3_audio_vae_fp32.safetensors\", \"dir\": \"vae\", \"size\": \"0.60 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_audio_vae_fp32.safetensors\", \"note\": \"the sound\"}, {\"name\": \"pika_h3_flex_ref2va_v1_bf16.safetensors\", \"dir\": \"loras\", \"size\": \"1.96 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/loras/pika_h3_flex_ref2va_v1_bf16.safetensors\", \"note\": \"Pika's add-on, already in the LoRA Loader\"}, {\"name\": \"minimax_h3_ref2va_pruned_w6a8.safetensors\", \"dir\": \"diffusion_models\", \"size\": \"15.98 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/diffusion_models/minimax_h3_ref2va_pruned_w6a8.safetensors\", \"note\": \"only for Low VRAM: use it in place of the first file\"}, {\"name\": \"minimax_h3_video_vae_int8_convrot.safetensors\", \"dir\": \"vae\", \"size\": \"2.81 GB\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3/resolve/main/vae/minimax_h3_video_vae_int8_convrot.safetensors\", \"note\": \"only for Low VRAM: use it in place of the VAE above\"}, {\"name\": \"qwen3vl_8b_int8_convrot.safetensors\", \"dir\": \"text_encoders\", \"size\": \"9.35 GB\", \"url\": \"https://huggingface.co/Comfy-Org/Qwen-Image-2.1/resolve/main/text_encoders/qwen3vl_8b_int8_convrot.safetensors\", \"note\": \"only for Auto prompt: the small text model\"}], \"packs\": [{\"name\": \"ComfyUI-AusBoss\", \"url\": \"https://github.com/ausboss/ComfyUI-AusBoss\", \"node\": \"AUSBOSS_NODES_Callout\"}], \"links\": [{\"label\": \"YouTube \u00b7 20 things you can do with an edit model\", \"url\": \"https://youtu.be/GociGWQQDSs\"}, {\"label\": \"YouTube \u00b7 ausbossdev\", \"url\": \"https://www.youtube.com/@ausbossdev\"}, {\"label\": \"Pika H3 Flex \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Pika-Labs/Pika-H3-Flex\"}, {\"label\": \"MiniMax H3 files \u00b7 Hugging Face\", \"url\": \"https://huggingface.co/Comfy-Org/MiniMax-H3\"}, {\"label\": \"GitHub \u00b7 ausboss\", \"url\": \"https://github.com/ausboss\"}, {\"label\": \"Civitai \u00b7 AusBoss\", \"url\": \"https://civitai.com/user/AusBoss\"}, {\"label\": \"X \u00b7 Zanzibased\", \"url\": \"https://x.com/Zanzibased\"}]}"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -1456,14 +1456,14 @@
"ver": "0.43.2"
},
"widgets_values": [
"01_card_declined.mp4",
"",
0,
0,
10,
""
],
"widgets_values_named": {
"audio": "01_card_declined.mp4",
"audio": "",
"start_seconds": 0,
"end_seconds": 0,
"max_seconds": 10,
@@ -1566,14 +1566,14 @@
"ver": "0.43.2"
},
"widgets_values": [
"01_card_declined.mp4",
"",
0,
0,
10,
""
],
"widgets_values_named": {
"audio": "01_card_declined.mp4",
"audio": "",
"start_seconds": 0,
"end_seconds": 0,
"max_seconds": 10,
@@ -1983,7 +1983,7 @@
"links": []
}
],
"title": "Video - Swap or copy moves",
"title": "Video - Your clip",
"properties": {
"Node name for S&R": "AUSBOSS_NODES_VideoCropRotatePadClip",
"cnr_id": "ausboss-nodes",
@@ -3452,10 +3452,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"{\"v\": 1, \"title\": \"Settings\", \"subtitle\": \"Only Picture 1 is on as it opens. Load it, type, press Run.\", \"author\": \"\", \"body\": \"### Swap someone in a video\\n1. Switch on **Video** and **Keep the clip's sound**, and load your clip.\\n2. Load the new person in **Picture 1**.\\n3. Clear **What happens** and press **Run**.\\n\\nTwo people in the clip? Type who goes, like \\\"the man in the hat\\\".\\n\\n### Good to know\\n- Click an arrow on a note to jump to what it points at.\\n- Purple nodes are switched off and need no file. The switches turn them on.\\n\\n### A clip came out wrong?\\nRun it again: the seed changes after every run. Still wrong? Read **Prompt H3 sees** on the right, then say it more plainly, one thing at a time. \\\"Value not in list\\\" means a file is missing.\", \"models\": [], \"packs\": [], \"links\": [], \"layout\": \"card\", \"accent\": \"\"}"
"{\"v\": 1, \"title\": \"Settings\", \"subtitle\": \"Only Picture 1 is on as it opens. Pick what you are making, then press Run.\", \"author\": \"\", \"body\": \"### Make a clip from pictures\\n1. Load **Picture 1** and pick its job on **H3 Prompt Writer**: person, place, outfit or thing.\\n2. Type what happens, one line for each thing.\\n3. Press **Run**.\\n\\n### Swap someone in a video\\n1. Switch on **Video** and **Keep the clip's sound**, and load your clip.\\n2. Load the new person in **Picture 1**.\\n3. Set the video job to **swap the person** on **H3 Prompt Writer**.\\n4. Clear **What happens** and press **Run**.\\n\\nSwapping two people? Switch on **Picture 2** too: Picture 1 takes the left one's place and Picture 2 the right one's. Or type who goes, one line each: `@1 the man in the hat`. Two can take a couple of runs.\\n\\n### Put a hat or an outfit on the person in your video\\n1. Switch on **Video**, **Keep the clip's sound** and **Picture 2**, and load your clip.\\n2. Load a still of the person from the video in **Picture 1**. A pasted screenshot works. Load the hat or outfit in **Picture 2**.\\n3. On **H3 Prompt Writer**, pick person for Picture 1, outfit for Picture 2, and the video job **swap the person**.\\n4. Type `@1 wears @2 in place of his cap` and press **Run**.\\n\\n### Good to know\\n- Click an arrow on a note to jump to what it points at.\\n- Purple nodes are switched off and need no file. The switches turn them on.\\n\\n### A clip came out wrong?\\nRun it again: the seed changes after every run. Still wrong? Read **Prompt H3 sees** on the right, then say it more plainly, one thing at a time. \\\"Value not in list\\\" means a file is missing.\", \"models\": [], \"packs\": [], \"links\": [], \"layout\": \"card\", \"accent\": \"\"}"
],
"widgets_values_named": {
"note": "{\"v\": 1, \"title\": \"Settings\", \"subtitle\": \"Only Picture 1 is on as it opens. Load it, type, press Run.\", \"author\": \"\", \"body\": \"### Swap someone in a video\\n1. Switch on **Video** and **Keep the clip's sound**, and load your clip.\\n2. Load the new person in **Picture 1**.\\n3. Clear **What happens** and press **Run**.\\n\\nTwo people in the clip? Type who goes, like \\\"the man in the hat\\\".\\n\\n### Good to know\\n- Click an arrow on a note to jump to what it points at.\\n- Purple nodes are switched off and need no file. The switches turn them on.\\n\\n### A clip came out wrong?\\nRun it again: the seed changes after every run. Still wrong? Read **Prompt H3 sees** on the right, then say it more plainly, one thing at a time. \\\"Value not in list\\\" means a file is missing.\", \"models\": [], \"packs\": [], \"links\": [], \"layout\": \"card\", \"accent\": \"\"}"
"note": "{\"v\": 1, \"title\": \"Settings\", \"subtitle\": \"Only Picture 1 is on as it opens. Pick what you are making, then press Run.\", \"author\": \"\", \"body\": \"### Make a clip from pictures\\n1. Load **Picture 1** and pick its job on **H3 Prompt Writer**: person, place, outfit or thing.\\n2. Type what happens, one line for each thing.\\n3. Press **Run**.\\n\\n### Swap someone in a video\\n1. Switch on **Video** and **Keep the clip's sound**, and load your clip.\\n2. Load the new person in **Picture 1**.\\n3. Set the video job to **swap the person** on **H3 Prompt Writer**.\\n4. Clear **What happens** and press **Run**.\\n\\nSwapping two people? Switch on **Picture 2** too: Picture 1 takes the left one's place and Picture 2 the right one's. Or type who goes, one line each: `@1 the man in the hat`. Two can take a couple of runs.\\n\\n### Put a hat or an outfit on the person in your video\\n1. Switch on **Video**, **Keep the clip's sound** and **Picture 2**, and load your clip.\\n2. Load a still of the person from the video in **Picture 1**. A pasted screenshot works. Load the hat or outfit in **Picture 2**.\\n3. On **H3 Prompt Writer**, pick person for Picture 1, outfit for Picture 2, and the video job **swap the person**.\\n4. Type `@1 wears @2 in place of his cap` and press **Run**.\\n\\n### Good to know\\n- Click an arrow on a note to jump to what it points at.\\n- Purple nodes are switched off and need no file. The switches turn them on.\\n\\n### A clip came out wrong?\\nRun it again: the seed changes after every run. Still wrong? Read **Prompt H3 sees** on the right, then say it more plainly, one thing at a time. \\\"Value not in list\\\" means a file is missing.\", \"models\": [], \"packs\": [], \"links\": [], \"layout\": \"card\", \"accent\": \"\"}"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -3495,10 +3495,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"{\"v\": 1, \"title\": \"Your pictures\", \"subtitle\": \"Give each picture one job on H3 Prompt Writer. Type @1 for Picture 1, @2 for Picture 2.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **person**: a clear photo of one person. They go wherever your lines say. Name no place and they stay where the picture shows.\\n- **character sheet**: for a swap, crop it to one view with the blue handles. A whole sheet can flash up at the start, and a second picture of the same person becomes a second person.\\n- **place**: a place with nobody in it. Pale bars at the sides of the clip? Crop this picture to the clip's shape with the blue handles.\\n- **outfit** or **thing**: nobody in the picture. A person in it pulls the face toward theirs, so crop the head off with the blue handles.\\n- **style**: only the look is used.\\n- **start on it** or **end on it**: the first or the last moment of the clip.\", \"models\": [], \"packs\": [], \"links\": []}"
"{\"v\": 1, \"title\": \"Your pictures\", \"subtitle\": \"Give each picture one job on H3 Prompt Writer, under the words. Picture 1 opens as person, so change it when you load a place, a hat or a thing. Type @1 for Picture 1, @2 for Picture 2.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **person**: a clear photo of one person. They go wherever your lines say. Name no place and they stay where the picture shows.\\n- **character sheet**: for a swap, crop it to one view with the blue handles. A whole sheet can flash up at the start, and a second picture of the same person becomes a second person.\\n- **place**: a place with nobody in it. Pale bars at the sides of the clip? Crop this picture to the clip's shape with the blue handles.\\n- **outfit** or **thing**: nobody in the picture. A person in it pulls the face toward theirs, so crop the head off with the blue handles. To put it on the person in your video, see **A new hat or outfit** in Recipes.\\n- **style**: only the look is used.\\n- **start on it** or **end on it**: the first or the last moment of the clip.\", \"models\": [], \"packs\": [], \"links\": []}"
],
"widgets_values_named": {
"note": "{\"v\": 1, \"title\": \"Your pictures\", \"subtitle\": \"Give each picture one job on H3 Prompt Writer. Type @1 for Picture 1, @2 for Picture 2.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **person**: a clear photo of one person. They go wherever your lines say. Name no place and they stay where the picture shows.\\n- **character sheet**: for a swap, crop it to one view with the blue handles. A whole sheet can flash up at the start, and a second picture of the same person becomes a second person.\\n- **place**: a place with nobody in it. Pale bars at the sides of the clip? Crop this picture to the clip's shape with the blue handles.\\n- **outfit** or **thing**: nobody in the picture. A person in it pulls the face toward theirs, so crop the head off with the blue handles.\\n- **style**: only the look is used.\\n- **start on it** or **end on it**: the first or the last moment of the clip.\", \"models\": [], \"packs\": [], \"links\": []}"
"note": "{\"v\": 1, \"title\": \"Your pictures\", \"subtitle\": \"Give each picture one job on H3 Prompt Writer, under the words. Picture 1 opens as person, so change it when you load a place, a hat or a thing. Type @1 for Picture 1, @2 for Picture 2.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **person**: a clear photo of one person. They go wherever your lines say. Name no place and they stay where the picture shows.\\n- **character sheet**: for a swap, crop it to one view with the blue handles. A whole sheet can flash up at the start, and a second picture of the same person becomes a second person.\\n- **place**: a place with nobody in it. Pale bars at the sides of the clip? Crop this picture to the clip's shape with the blue handles.\\n- **outfit** or **thing**: nobody in the picture. A person in it pulls the face toward theirs, so crop the head off with the blue handles. To put it on the person in your video, see **A new hat or outfit** in Recipes.\\n- **style**: only the look is used.\\n- **start on it** or **end on it**: the first or the last moment of the clip.\", \"models\": [], \"packs\": [], \"links\": []}"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -3538,10 +3538,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"{\"v\": 1, \"title\": \"Recipes\", \"subtitle\": \"What to turn on, and what to type.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **A story across places.** Nothing extra. One line for each place, with a blank line between.\\n- **Your own place.** Picture 2 as place: `@1 sits at the counter in @2`\\n- **Two people.** Picture 2 as person: `@1 and @2 sit side by side on a night bus`\\n- **A new outfit.** Picture 2 as outfit: `@1 walks down a runway wearing @2`\\n- **A product film.** Picture 1 as thing: `@1 spins slowly on black glass`\\n- **Copy a dance.** Video on, as copy its moves: `@1 dances on a rooftop at sunset`\\n- **That dance, that outfit.** Video on, Picture 2 as outfit: `@1 dances on a rooftop wearing @2`\\n- **Put someone in a video.** Video on, as swap the person. Type nothing.\\n- **A longer story.** Video on, as keep going. Load your last clip and type what comes next.\", \"models\": [], \"packs\": [], \"links\": []}"
"{\"v\": 1, \"title\": \"Recipes\", \"subtitle\": \"What to turn on, and what to type.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **A story across places.** Nothing extra. One line for each place, with a blank line between.\\n- **Your own place.** Picture 2 as place: `@1 sits at the counter in @2`\\n- **Two people.** Picture 2 as person: `@1 and @2 sit side by side on a night bus`\\n- **A new outfit.** Picture 2 as outfit: `@1 walks down a runway wearing @2`\\n- **A product film.** Picture 1 as thing: `@1 spins slowly on black glass`\\n- **Copy a dance.** Video on, as copy its moves. Picture 1 is your person: `@1 dances on a rooftop at sunset`\\n- **That dance, that outfit.** Video on, as copy its moves. Picture 1 is your person, Picture 2 as outfit: `@1 dances on a rooftop wearing @2`\\n- **Put someone in a video.** Video on, as swap the person. Picture 1 is the new person. Type nothing.\\n- **A new hat or outfit on the person in your video.** Video on, as swap the person. Picture 1 is a still of them from the video (a pasted screenshot works), as person. Picture 2 is the hat or outfit, as outfit: `@1 wears @2 in place of his cap`\\n- **A longer story.** Video on, as keep going. Load your last clip and type what comes next.\", \"models\": [], \"packs\": [], \"links\": []}"
],
"widgets_values_named": {
"note": "{\"v\": 1, \"title\": \"Recipes\", \"subtitle\": \"What to turn on, and what to type.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **A story across places.** Nothing extra. One line for each place, with a blank line between.\\n- **Your own place.** Picture 2 as place: `@1 sits at the counter in @2`\\n- **Two people.** Picture 2 as person: `@1 and @2 sit side by side on a night bus`\\n- **A new outfit.** Picture 2 as outfit: `@1 walks down a runway wearing @2`\\n- **A product film.** Picture 1 as thing: `@1 spins slowly on black glass`\\n- **Copy a dance.** Video on, as copy its moves: `@1 dances on a rooftop at sunset`\\n- **That dance, that outfit.** Video on, Picture 2 as outfit: `@1 dances on a rooftop wearing @2`\\n- **Put someone in a video.** Video on, as swap the person. Type nothing.\\n- **A longer story.** Video on, as keep going. Load your last clip and type what comes next.\", \"models\": [], \"packs\": [], \"links\": []}"
"note": "{\"v\": 1, \"title\": \"Recipes\", \"subtitle\": \"What to turn on, and what to type.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"- **A story across places.** Nothing extra. One line for each place, with a blank line between.\\n- **Your own place.** Picture 2 as place: `@1 sits at the counter in @2`\\n- **Two people.** Picture 2 as person: `@1 and @2 sit side by side on a night bus`\\n- **A new outfit.** Picture 2 as outfit: `@1 walks down a runway wearing @2`\\n- **A product film.** Picture 1 as thing: `@1 spins slowly on black glass`\\n- **Copy a dance.** Video on, as copy its moves. Picture 1 is your person: `@1 dances on a rooftop at sunset`\\n- **That dance, that outfit.** Video on, as copy its moves. Picture 1 is your person, Picture 2 as outfit: `@1 dances on a rooftop wearing @2`\\n- **Put someone in a video.** Video on, as swap the person. Picture 1 is the new person. Type nothing.\\n- **A new hat or outfit on the person in your video.** Video on, as swap the person. Picture 1 is a still of them from the video (a pasted screenshot works), as person. Picture 2 is the hat or outfit, as outfit: `@1 wears @2 in place of his cap`\\n- **A longer story.** Video on, as keep going. Load your last clip and type what comes next.\", \"models\": [], \"packs\": [], \"links\": []}"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -3581,10 +3581,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"{\"v\": 1, \"title\": \"Your video and sound\", \"subtitle\": \"Up to 15 seconds. Pick its job on H3 Prompt Writer.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"Drag the handles to the part you want. The clip takes this video's shape, and takes about three times as long to make.\\n\\n- **copy its moves**: your person does what the video shows. The clothes in the video stay unless your line names new ones.\\n- **swap the person**: the same video with your person in it. Type nothing. Two people in it? Type who goes: `the child in the seat`.\\n- **keep going**: more of the clip, from where it ends. Type what comes next. It saves the new part.\\n- **new voice**: the same video in another voice. Turn **Voice** on and put the words in quotes.\\n\\n### Voice and Song\\n**Voice**: about 10 seconds of someone talking, yours or one you have permission to use. Put the words in quotes, on the last line.\\n\\n**Song**: it plays as it is, and each moment moves onto its beat. With a voice too, it goes under the words.\", \"models\": [], \"packs\": [], \"links\": []}"
"{\"v\": 1, \"title\": \"Your video and sound\", \"subtitle\": \"Up to 15 seconds. Pick its job on H3 Prompt Writer.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"Drag the handles to the part you want. The clip takes this video's shape, and takes about three times as long to make.\\n\\n- **copy its moves**: your person does what the video shows. The clothes in the video stay unless your line names new ones.\\n- **swap the person**: the same video with your person in it. Type nothing. Two people in it? Type who goes: `the child in the seat`. Same person in a new hat or outfit? Load a still of them as person and the item as outfit (Recipes).\\n- **keep going**: more of the clip, from where it ends. Type what comes next. It saves the new part.\\n- **new voice**: the same video in another voice. Turn **Voice** on and put the words in quotes.\\n\\n### Voice and Song\\n**Voice**: about 10 seconds of someone talking, yours or one you have permission to use. Put the words in quotes, on the last line.\\n\\n**Song**: it plays as it is, and each moment moves onto its beat. With a voice too, it goes under the words.\", \"models\": [], \"packs\": [], \"links\": []}"
],
"widgets_values_named": {
"note": "{\"v\": 1, \"title\": \"Your video and sound\", \"subtitle\": \"Up to 15 seconds. Pick its job on H3 Prompt Writer.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"Drag the handles to the part you want. The clip takes this video's shape, and takes about three times as long to make.\\n\\n- **copy its moves**: your person does what the video shows. The clothes in the video stay unless your line names new ones.\\n- **swap the person**: the same video with your person in it. Type nothing. Two people in it? Type who goes: `the child in the seat`.\\n- **keep going**: more of the clip, from where it ends. Type what comes next. It saves the new part.\\n- **new voice**: the same video in another voice. Turn **Voice** on and put the words in quotes.\\n\\n### Voice and Song\\n**Voice**: about 10 seconds of someone talking, yours or one you have permission to use. Put the words in quotes, on the last line.\\n\\n**Song**: it plays as it is, and each moment moves onto its beat. With a voice too, it goes under the words.\", \"models\": [], \"packs\": [], \"links\": []}"
"note": "{\"v\": 1, \"title\": \"Your video and sound\", \"subtitle\": \"Up to 15 seconds. Pick its job on H3 Prompt Writer.\", \"author\": \"AusBoss\", \"layout\": \"card\", \"accent\": \"\", \"body\": \"Drag the handles to the part you want. The clip takes this video's shape, and takes about three times as long to make.\\n\\n- **copy its moves**: your person does what the video shows. The clothes in the video stay unless your line names new ones.\\n- **swap the person**: the same video with your person in it. Type nothing. Two people in it? Type who goes: `the child in the seat`. Same person in a new hat or outfit? Load a still of them as person and the item as outfit (Recipes).\\n- **keep going**: more of the clip, from where it ends. Type what comes next. It saves the new part.\\n- **new voice**: the same video in another voice. Turn **Voice** on and put the words in quotes.\\n\\n### Voice and Song\\n**Voice**: about 10 seconds of someone talking, yours or one you have permission to use. Put the words in quotes, on the last line.\\n\\n**Song**: it plays as it is, and each moment moves onto its beat. With a voice too, it goes under the words.\", \"models\": [], \"packs\": [], \"links\": []}"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -3738,7 +3738,7 @@
"switches": [
{
"id": 5,
"title": "Video: swap or copy moves",
"title": "Video: your clip",
"nodes": [
150
],
@@ -3850,7 +3850,7 @@
"fast test": false
},
"150": {
"megapixels": 1
"megapixels": 0.41
}
}
}
@@ -3987,10 +3987,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"\u2b05\ufe0f#224 **Video**: swap someone in or copy the moves. Up to 10 s, at about 480p.\n\u2b05\ufe0f#224 **Keep the clip's sound**: its own words and music, for a swap.\n\u2198\ufe0f#151 **Voice**: 10 seconds of talking, with the words in quotes on the last line.\n\u2198\ufe0f#152 **Song**: plays under the clip."
"\u2b05\ufe0f#224 **Video**: swap someone in, change what they wear, copy the moves or keep it going. Up to 10 s, at about 480p.\n\u2b05\ufe0f#224 **Keep the clip's sound**: its own words and music, for a swap or a new outfit.\n\u2198\ufe0f#151 **Voice**: 10 seconds of talking, with the words in quotes on the last line.\n\u2198\ufe0f#152 **Song**: plays under the clip."
],
"widgets_values_named": {
"text": "\u2b05\ufe0f#224 **Video**: swap someone in or copy the moves. Up to 10 s, at about 480p.\n\u2b05\ufe0f#224 **Keep the clip's sound**: its own words and music, for a swap.\n\u2198\ufe0f#151 **Voice**: 10 seconds of talking, with the words in quotes on the last line.\n\u2198\ufe0f#152 **Song**: plays under the clip."
"text": "\u2b05\ufe0f#224 **Video**: swap someone in, change what they wear, copy the moves or keep it going. Up to 10 s, at about 480p.\n\u2b05\ufe0f#224 **Keep the clip's sound**: its own words and music, for a swap or a new outfit.\n\u2198\ufe0f#151 **Voice**: 10 seconds of talking, with the words in quotes on the last line.\n\u2198\ufe0f#152 **Song**: plays under the clip."
},
"color": "#07090a",
"bgcolor": "#07090a"
@@ -5207,7 +5207,7 @@
]
},
{
"id": "f14285c7-e429-4811-9dce-ac349af3a4e5",
"id": "f836716c-c34c-4248-8c23-d60864273611",
"name": "clip sound",
"type": "AUDIO",
"linkIds": [
@@ -5219,7 +5219,7 @@
]
},
{
"id": "d619bfaa-dc51-4cbd-a4b1-e5822815a73c",
"id": "dfc070d2-400b-4f79-98da-7844a3cd1818",
"name": "steer mouths",
"type": "BOOLEAN",
"linkIds": [
@@ -7937,10 +7937,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"floor(a * c * (1 - 0.375 * b) / 16) * 16"
"floor(a * c * (1 - 0.375 * b) / 32) * 32"
],
"widgets_values_named": {
"expression": "floor(a * c * (1 - 0.375 * b) / 16) * 16"
"expression": "floor(a * c * (1 - 0.375 * b) / 32) * 32"
},
"color": "#14424d",
"bgcolor": "#161f21"
@@ -8014,10 +8014,10 @@
"ver": "2.21.0"
},
"widgets_values": [
"floor(a * c * (1 - 0.375 * b) / 16) * 16"
"floor(a * c * (1 - 0.375 * b) / 32) * 32"
],
"widgets_values_named": {
"expression": "floor(a * c * (1 - 0.375 * b) / 16) * 16"
"expression": "floor(a * c * (1 - 0.375 * b) / 32) * 32"
},
"color": "#14424d",
"bgcolor": "#161f21"
+8
View File
@@ -37,6 +37,12 @@ NEEDS_A_PERSON = {
MOVES: "To copy the moves, connect a picture of your person and pick person for it.",
SWAP: "To swap the person, connect a picture of the new person and pick person for it.",
}
# A hat or a shirt with no person picture: the user wants the video's own person to wear it.
DRESS_THE_VIDEO_PERSON = (
"To put this on the person in your video, load a still of them from the video as Picture 1 "
"and pick person for it. Give the hat or outfit its own picture, pick outfit or thing, and type "
"\"@1 wears @2\" with video job swap the person."
)
# (what the label is, how it is kept). {picture} is H3's number for the picture.
JOB_WORDS = {
@@ -241,6 +247,8 @@ class Cast:
if not self.pictures and not self.video:
return NOTHING_IN
if self.video in NEEDS_A_PERSON and not self.people:
if self.of(OUTFIT, THING):
return DRESS_THE_VIDEO_PERSON
return NEEDS_A_PERSON[self.video]
typed = sorted({int(number) for number in TOKEN.findall(text)} - {0})
slots = {picture.slot: picture for picture in self.pictures}
+54
View File
@@ -63,6 +63,58 @@ def named_copy_problems(node: dict) -> list[str]:
return [f"node {node['id']} has stale named widget values: {', '.join(stale)}"] if stale else []
def saved_widget(node: dict, name: str):
"""A widget's saved value by name, or KeyError when the node keeps no named copy of it."""
values = node.get("widgets_values")
if isinstance(values, dict) and name in values:
return values[name]
named = node.get("widgets_values_named")
if isinstance(named, dict) and name in named:
return named[name]
raise KeyError(name)
def switch_row_problems(card: dict, by_id: dict) -> list[str]:
"""A Workflow Switches row opens striped "changed", with neither off nor
on picked, when the values it sets are saved half one way and half the
other, or when its nodes run one way and its values say the other. Every
row of an example has to open plainly off or on."""
settings = (card.get("properties") or {}).get("ausboss_workflow_switches") or {}
problems = []
for row in settings.get("switches") or []:
title = row.get("title", row.get("id"))
sides = set()
on, off = row.get("on") or {}, row.get("off") or {}
for node_id, widgets in on.items():
node = by_id.get(int(node_id)) if str(node_id).isdigit() else None
if node is None or not isinstance(widgets, dict):
continue
for name, on_value in widgets.items():
off_value = (off.get(node_id) or {}).get(name)
lora_rows = isinstance(on_value, str) and on_value.startswith("[")
if isinstance(on_value, (dict, list)) or lora_rows or on_value == off_value:
continue # a LoRA stack is matched row by row, and a shared value says nothing
try:
saved = saved_widget(node, name)
except KeyError:
continue
if saved == on_value:
sides.add("on")
elif saved == off_value:
sides.add("off")
else:
sides.add(f"neither ({node_id} {name} is {saved!r}, not {on_value!r} or {off_value!r})")
members = [by_id[i] for i in row.get("nodes") or [] if i in by_id]
modes = {"on" if m.get("mode", 0) == 0 else "off" for m in members}
if len(modes) > 1:
problems.append(f"switch card {card['id']} row '{title}': some of its nodes are on and some off")
odd = sorted(side for side in sides if side not in ("on", "off"))
if odd or len(sides) > 1 or (sides and modes and sides != modes):
detail = "; ".join(odd) if odd else f"values say {'/'.join(sorted(sides))}, nodes say {'/'.join(sorted(modes)) or '-'}"
problems.append(f"switch card {card['id']} row '{title}' opens as changed: {detail}")
return problems
def workflow_problems(data: dict) -> list[str]:
problems = []
nodes = data.get("nodes", [])
@@ -112,6 +164,8 @@ def workflow_problems(data: dict) -> list[str]:
problems.append(f"saved zoom {scale} is below {MIN_ZOOM}; widget text would not draw")
for n in nodes:
problems.extend(named_copy_problems(n))
if n["type"] == "AUSBOSS_NODES_WorkflowSwitches":
problems.extend(switch_row_problems(n, by_id))
if n["type"] in CORE_LORA_LOADERS:
problems.append(f"node {n['id']} loads a LoRA with core {n['type']}; examples use LoRA Loader 🆎")
selected = selected_files(n)
+6
View File
@@ -652,6 +652,12 @@ class VideoJobTests(unittest.TestCase):
cast = Cast(number_pictures({1: "place"}, "copy its moves"), "copy its moves")
self.assertIn("To copy the moves", cast.problem("She dances."))
def test_a_hat_with_no_person_picture_says_how_to_put_it_on_the_video_person(self):
for job in ("outfit", "thing"):
for video in ("swap the person", "copy its moves"):
cast = Cast(number_pictures({1: job}, video), video)
self.assertIn("load a still of them from the video as Picture 1", cast.problem("He wears @1."))
def test_a_swap_with_nobody_to_put_in_says_so(self):
with self.assertRaisesRegex(ValueError, "new person"):
write_prompt("", jobs={}, video="swap the person")
+18
View File
@@ -38,6 +38,24 @@ class WorkflowContractTests(unittest.TestCase):
graph["nodes"][0]["widgets_values_named"] = {"video": "someone_else.mp4", "start_seconds": 0, "upload": ""}
self.assertIn("stale named widget values: video", " ".join(workflow_problems(graph)))
def test_a_switch_row_must_open_plainly_off_or_on(self):
graph = good_graph()
graph["nodes"][0]["widgets_values"] = {"megapixels": 0.41}
card = {"id": 4, "type": "AUSBOSS_NODES_WorkflowSwitches", "pos": [0, 300], "size": [100, 40], "properties": {
"ausboss_workflow_switches": {"switches": [{"id": 9, "title": "Fast test", "nodes": [],
"on": {"1": {"megapixels": 0.26}}, "off": {"1": {"megapixels": 1}}}]}}}
graph["nodes"].append(card)
graph["last_node_id"] = 4
graph["groups"][0]["bounding"] = [-20, 40, 320, 320]
self.assertIn("row 'Fast test' opens as changed", " ".join(workflow_problems(graph)))
card["properties"]["ausboss_workflow_switches"]["switches"][0]["off"] = {"1": {"megapixels": 0.41}}
self.assertEqual(workflow_problems(graph), [])
graph["nodes"][1]["widgets_values"] = {"steps": 8}
graph["nodes"][1]["mode"] = 4
card["properties"]["ausboss_workflow_switches"]["switches"].append(
{"id": 10, "title": "Turbo", "nodes": [2], "on": {"2": {"steps": 8}}, "off": {"2": {"steps": 20}}})
self.assertIn("row 'Turbo' opens as changed: values say on, nodes say off", " ".join(workflow_problems(graph)))
def test_workflow_id_and_zoom(self):
graph = good_graph()
graph["id"] = "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b"