diff --git a/example_workflows/wanvideo_I2V_InfiniteTalk_example_02.json b/example_workflows/wanvideo_I2V_InfiniteTalk_example_03.json similarity index 96% rename from example_workflows/wanvideo_I2V_InfiniteTalk_example_02.json rename to example_workflows/wanvideo_I2V_InfiniteTalk_example_03.json index 2834730..e1c88ad 100644 --- a/example_workflows/wanvideo_I2V_InfiniteTalk_example_02.json +++ b/example_workflows/wanvideo_I2V_InfiniteTalk_example_03.json @@ -1,44 +1,9 @@ { "id": "8b7a9a57-2303-4ef5-9fc2-bf41713bd1fc", "revision": 0, - "last_node_id": 304, - "last_link_id": 545, + "last_node_id": 310, + "last_link_id": 551, "nodes": [ - { - "id": 120, - "type": "MultiTalkModelLoader", - "pos": [ - 592.73583984375, - -2520.13525390625 - ], - "size": [ - 511.7737121582031, - 66.51400756835938 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "model", - "type": "MULTITALKMODEL", - "links": [ - 355 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", - "Node name for S&R": "MultiTalkModelLoader" - }, - "widgets_values": [ - "WanVideo\\InfiniteTalk\\InfiniteTalk\\Wan2_1-InfiniteTalk_Single_Q8.gguf" - ], - "color": "#223", - "bgcolor": "#335" - }, { "id": 239, "type": "MarkdownNote", @@ -51,7 +16,7 @@ 214.95587158203125 ], "flags": {}, - "order": 1, + "order": 0, "mode": 0, "inputs": [], "outputs": [], @@ -75,7 +40,7 @@ 82 ], "flags": {}, - "order": 2, + "order": 1, "mode": 0, "inputs": [ { @@ -161,7 +126,7 @@ "flags": { "collapsed": true }, - "order": 36, + "order": 38, "mode": 0, "inputs": [ { @@ -199,7 +164,7 @@ 58 ], "flags": {}, - "order": 3, + "order": 2, "mode": 0, "inputs": [], "outputs": [ @@ -276,7 +241,7 @@ "flags": { "collapsed": true }, - "order": 31, + "order": 30, "mode": 0, "inputs": [ { @@ -316,7 +281,7 @@ "flags": { "collapsed": true }, - "order": 32, + "order": 31, "mode": 0, "inputs": [ { @@ -356,7 +321,7 @@ "flags": { "collapsed": true }, - "order": 4, + "order": 3, "mode": 0, "inputs": [], "outputs": [ @@ -390,7 +355,7 @@ "flags": { "collapsed": true }, - "order": 5, + "order": 4, "mode": 0, "inputs": [], "outputs": [ @@ -422,7 +387,7 @@ 150 ], "flags": {}, - "order": 6, + "order": 5, "mode": 0, "inputs": [ { @@ -473,7 +438,7 @@ 202 ], "flags": {}, - "order": 7, + "order": 6, "mode": 0, "inputs": [], "outputs": [ @@ -514,7 +479,7 @@ 58 ], "flags": {}, - "order": 8, + "order": 7, "mode": 0, "inputs": [], "outputs": [ @@ -550,7 +515,7 @@ 58 ], "flags": {}, - "order": 9, + "order": 8, "mode": 0, "inputs": [], "outputs": [ @@ -652,7 +617,7 @@ "flags": { "collapsed": true }, - "order": 10, + "order": 9, "mode": 0, "inputs": [], "outputs": [ @@ -672,76 +637,6 @@ "color": "#233", "bgcolor": "#355" }, - { - "id": 242, - "type": "GetNode", - "pos": [ - 3670.50830078125, - -1982.0732421875 - ], - "size": [ - 210, - 60 - ], - "flags": { - "collapsed": true - }, - "order": 11, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "WANVAE", - "type": "WANVAE", - "links": [ - 438 - ] - } - ], - "title": "Get_VAE", - "properties": {}, - "widgets_values": [ - "VAE" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 270, - "type": "INTConstant", - "pos": [ - 2655.538330078125, - -2261.7578125 - ], - "size": [ - 210, - 58 - ], - "flags": {}, - "order": 12, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "value", - "type": "INT", - "links": [ - 472 - ] - } - ], - "title": "Max frames", - "properties": { - "cnr_id": "comfyui-kjnodes", - "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324", - "Node name for S&R": "INTConstant" - }, - "widgets_values": [ - 1000 - ], - "color": "#1b4669", - "bgcolor": "#29699c" - }, { "id": 294, "type": "SetNode", @@ -827,7 +722,7 @@ "flags": { "collapsed": true }, - "order": 33, + "order": 35, "mode": 0, "inputs": [ { @@ -960,7 +855,7 @@ 143.7332305908203 ], "flags": {}, - "order": 13, + "order": 10, "mode": 0, "inputs": [], "outputs": [], @@ -983,7 +878,7 @@ 314 ], "flags": {}, - "order": 30, + "order": 34, "mode": 0, "inputs": [ { @@ -1011,7 +906,7 @@ "link": null }, { - "name": "vace_model", + "name": "extra_model", "shape": 7, "type": "VACEPATH", "link": null @@ -1035,7 +930,7 @@ "link": null }, { - "name": "extra_model", + "name": "vace_model", "shape": 7, "type": "VACEPATH", "link": null @@ -1077,7 +972,7 @@ 202 ], "flags": {}, - "order": 14, + "order": 11, "mode": 0, "inputs": [], "outputs": [ @@ -1118,7 +1013,7 @@ "flags": { "collapsed": true }, - "order": 15, + "order": 12, "mode": 0, "inputs": [], "outputs": [ @@ -1138,141 +1033,12 @@ "color": "#1b4669", "bgcolor": "#29699c" }, - { - "id": 130, - "type": "WanVideoDecode", - "pos": [ - 3675.3330078125, - -1893.888671875 - ], - "size": [ - 315, - 198 - ], - "flags": {}, - "order": 45, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 438 - }, - { - "name": "samples", - "type": "LATENT", - "link": 530 - } - ], - "outputs": [ - { - "name": "images", - "type": "IMAGE", - "slot_index": 0, - "links": [ - 493 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "c3ee35f3ece76e38099dc516182d69b406e16772", - "Node name for S&R": "WanVideoDecode" - }, - "widgets_values": [ - false, - 272, - 272, - 144, - 128, - "default" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 131, - "type": "VHS_VideoCombine", - "pos": [ - 3689.34814453125, - -1589.9613037109375 - ], - "size": [ - 991.5499877929688, - 1319.550048828125 - ], - "flags": {}, - "order": 46, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 493 - }, - { - "name": "audio", - "shape": 7, - "type": "AUDIO", - "link": 449 - }, - { - "name": "meta_batch", - "shape": 7, - "type": "VHS_BatchManager", - "link": null - }, - { - "name": "vae", - "shape": 7, - "type": "VAE", - "link": null - } - ], - "outputs": [ - { - "name": "Filenames", - "type": "VHS_FILENAMES", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-videohelpersuite", - "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", - "Node name for S&R": "VHS_VideoCombine" - }, - "widgets_values": { - "frame_rate": 25, - "loop_count": 0, - "filename_prefix": "WanVideo2_1_InfiniteTalk", - "format": "video/h264-mp4", - "pix_fmt": "yuv420p", - "crf": 19, - "save_metadata": true, - "trim_to_audio": false, - "pingpong": false, - "save_output": false, - "videopreview": { - "hidden": false, - "paused": false, - "params": { - "filename": "WanVideo2_1_InfiniteTalk_00004-audio.mp4", - "subfolder": "", - "type": "temp", - "format": "video/h264-mp4", - "frame_rate": 25, - "workflow": "WanVideo2_1_InfiniteTalk_00004.png", - "fullpath": "N:\\AI\\ComfyUI\\temp\\WanVideo2_1_InfiniteTalk_00004-audio.mp4" - } - } - } - }, { "id": 254, "type": "GetNode", "pos": [ - 3683.283935546875, - -1643.584228515625 + 3663.662841796875, + -1884.486328125 ], "size": [ 210, @@ -1281,7 +1047,7 @@ "flags": { "collapsed": true }, - "order": 16, + "order": 13, "mode": 0, "inputs": [], "outputs": [ @@ -1315,7 +1081,7 @@ "flags": { "collapsed": false }, - "order": 37, + "order": 36, "mode": 0, "inputs": [ { @@ -1363,174 +1129,6 @@ }, "widgets_values": [] }, - { - "id": 241, - "type": "WanVideoTextEncodeCached", - "pos": [ - 2281.288330078125, - -1946.174072265625 - ], - "size": [ - 465.5179138183594, - 386.354248046875 - ], - "flags": {}, - "order": 17, - "mode": 0, - "inputs": [ - { - "name": "extender_args", - "shape": 7, - "type": "WANVIDEOPROMPTEXTENDER_ARGS", - "link": null - } - ], - "outputs": [ - { - "name": "text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": [ - 437 - ] - }, - { - "name": "negative_text_embeds", - "type": "WANVIDEOTEXTEMBEDS", - "links": null - }, - { - "name": "positive_prompt", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "ff779c91714d8ee3484cd4119b082c72a1734b72", - "Node name for S&R": "WanVideoTextEncodeCached" - }, - "widgets_values": [ - "umt5-xxl-enc-bf16.safetensors", - "bf16", - "a man is talking", - "bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards", - "disabled", - false, - "gpu" - ], - "color": "#432", - "bgcolor": "#653" - }, - { - "id": 192, - "type": "WanVideoImageToVideoMultiTalk", - "pos": [ - 2836.906982421875, - -1288.3162841796875 - ], - "size": [ - 349.6015625, - 266 - ], - "flags": {}, - "order": 41, - "mode": 0, - "inputs": [ - { - "name": "vae", - "type": "WANVAE", - "link": 440 - }, - { - "name": "start_image", - "shape": 7, - "type": "IMAGE", - "link": 540 - }, - { - "name": "clip_embeds", - "shape": 7, - "type": "WANVIDIMAGE_CLIPEMBEDS", - "link": 433 - }, - { - "name": "width", - "type": "INT", - "widget": { - "name": "width" - }, - "link": 516 - }, - { - "name": "height", - "type": "INT", - "widget": { - "name": "height" - }, - "link": 517 - } - ], - "outputs": [ - { - "name": "image_embeds", - "type": "WANVIDIMAGE_EMBEDS", - "links": [ - 413 - ] - } - ], - "properties": { - "cnr_id": "ComfyUI-WanVideoWrapper", - "ver": "49430f900bf812a1e281560bafafd04c43dfdf13", - "Node name for S&R": "WanVideoImageToVideoMultiTalk" - }, - "widgets_values": [ - 832, - 480, - 81, - 9, - false, - "disabled", - false, - "infinitetalk" - ], - "color": "#322", - "bgcolor": "#533" - }, - { - "id": 244, - "type": "GetNode", - "pos": [ - 2825.2236328125, - -1325.1824951171875 - ], - "size": [ - 210, - 34 - ], - "flags": { - "collapsed": true - }, - "order": 18, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "WANVAE", - "type": "WANVAE", - "links": [ - 440 - ] - } - ], - "title": "Get_VAE", - "properties": {}, - "widgets_values": [ - "VAE" - ], - "color": "#322", - "bgcolor": "#533" - }, { "id": 283, "type": "GetNode", @@ -1545,7 +1143,7 @@ "flags": { "collapsed": true }, - "order": 19, + "order": 14, "mode": 0, "inputs": [], "outputs": [ @@ -1577,7 +1175,7 @@ 314 ], "flags": {}, - "order": 20, + "order": 15, "mode": 0, "inputs": [], "outputs": [ @@ -1616,7 +1214,7 @@ 336 ], "flags": {}, - "order": 34, + "order": 32, "mode": 0, "inputs": [ { @@ -1699,7 +1297,7 @@ 88 ], "flags": {}, - "order": 21, + "order": 16, "mode": 0, "inputs": [], "outputs": [], @@ -1724,7 +1322,7 @@ "flags": { "collapsed": true }, - "order": 35, + "order": 33, "mode": 0, "inputs": [ { @@ -1764,7 +1362,7 @@ 136 ], "flags": {}, - "order": 22, + "order": 17, "mode": 0, "inputs": [], "outputs": [ @@ -1799,7 +1397,7 @@ 106 ], "flags": {}, - "order": 23, + "order": 18, "mode": 0, "inputs": [], "outputs": [ @@ -1834,7 +1432,7 @@ 106 ], "flags": {}, - "order": 24, + "order": 19, "mode": 0, "inputs": [], "outputs": [ @@ -1867,7 +1465,7 @@ 46 ], "flags": {}, - "order": 38, + "order": 37, "mode": 0, "inputs": [ { @@ -1899,7 +1497,8 @@ "cnr_id": "ComfyUI-MelBandRoFormer", "ver": "b68d9077815387b64d596f8c39607052b95b6eba", "Node name for S&R": "MelBandRoFormerSampler" - } + }, + "widgets_values": [] }, { "id": 303, @@ -1913,7 +1512,7 @@ 125.51774597167969 ], "flags": {}, - "order": 25, + "order": 20, "mode": 0, "inputs": [], "outputs": [], @@ -1937,7 +1536,7 @@ 91.6759033203125 ], "flags": {}, - "order": 26, + "order": 21, "mode": 0, "inputs": [], "outputs": [], @@ -1961,7 +1560,7 @@ 58 ], "flags": {}, - "order": 27, + "order": 22, "mode": 0, "inputs": [], "outputs": [ @@ -1982,6 +1581,364 @@ "MelBandRoFormer\\MelBandRoformer_fp16.safetensors" ] }, + { + "id": 120, + "type": "MultiTalkModelLoader", + "pos": [ + 592.73583984375, + -2520.13525390625 + ], + "size": [ + 511.7737121582031, + 66.51400756835938 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "model", + "type": "MULTITALKMODEL", + "links": [ + 355 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "058286fc0f3b0651a2f6b68309df3f06e8332cc0", + "Node name for S&R": "MultiTalkModelLoader" + }, + "widgets_values": [ + "WanVideo\\InfiniteTalk\\Wan2_1-InfiniteTalk_Single_Q8.gguf" + ], + "color": "#223", + "bgcolor": "#335" + }, + { + "id": 244, + "type": "GetNode", + "pos": [ + 2835.034423828125, + -1351.3436279296875 + ], + "size": [ + 210, + 34 + ], + "flags": { + "collapsed": true + }, + "order": 24, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "WANVAE", + "type": "WANVAE", + "links": [ + 440 + ] + } + ], + "title": "Get_VAE", + "properties": {}, + "widgets_values": [ + "VAE" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 131, + "type": "VHS_VideoCombine", + "pos": [ + 3669.72705078125, + -1830.8634033203125 + ], + "size": [ + 991.5499877929688, + 1319.550048828125 + ], + "flags": {}, + "order": 46, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 551 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 449 + }, + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + } + ], + "outputs": [ + { + "name": "Filenames", + "type": "VHS_FILENAMES", + "links": null + } + ], + "properties": { + "cnr_id": "comfyui-videohelpersuite", + "ver": "0a75c7958fe320efcb052f1d9f8451fd20c730a8", + "Node name for S&R": "VHS_VideoCombine" + }, + "widgets_values": { + "frame_rate": 25, + "loop_count": 0, + "filename_prefix": "WanVideo2_1_InfiniteTalk", + "format": "video/h264-mp4", + "pix_fmt": "yuv420p", + "crf": 19, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "WanVideo2_1_InfiniteTalk_00003-audio.mp4", + "subfolder": "", + "type": "temp", + "format": "video/h264-mp4", + "frame_rate": 25, + "workflow": "WanVideo2_1_InfiniteTalk_00003.png", + "fullpath": "N:\\AI\\ComfyUI\\temp\\WanVideo2_1_InfiniteTalk_00003-audio.mp4" + } + } + } + }, + { + "id": 309, + "type": "WanVideoPassImagesFromSamples", + "pos": [ + 3642.054443359375, + -1970.1678466796875 + ], + "size": [ + 321.5958557128906, + 26 + ], + "flags": {}, + "order": 45, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 550 + } + ], + "outputs": [ + { + "name": "images", + "type": "IMAGE", + "links": [ + 551 + ] + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "e5955d83958f1c808c86e5be3804ca42b39ab3fa", + "Node name for S&R": "WanVideoPassImagesFromSamples" + } + }, + { + "id": 241, + "type": "WanVideoTextEncodeCached", + "pos": [ + 2281.288330078125, + -1946.174072265625 + ], + "size": [ + 465.5179138183594, + 386.354248046875 + ], + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "extender_args", + "shape": 7, + "type": "WANVIDEOPROMPTEXTENDER_ARGS", + "link": null + } + ], + "outputs": [ + { + "name": "text_embeds", + "type": "WANVIDEOTEXTEMBEDS", + "links": [ + 437 + ] + }, + { + "name": "negative_text_embeds", + "type": "WANVIDEOTEXTEMBEDS", + "links": null + }, + { + "name": "positive_prompt", + "type": "STRING", + "links": null + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "ff779c91714d8ee3484cd4119b082c72a1734b72", + "Node name for S&R": "WanVideoTextEncodeCached" + }, + "widgets_values": [ + "umt5-xxl-enc-bf16.safetensors", + "bf16", + "a woman is singing", + "bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards", + "disabled", + false, + "gpu" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 270, + "type": "INTConstant", + "pos": [ + 2655.538330078125, + -2261.7578125 + ], + "size": [ + 210, + 58 + ], + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "value", + "type": "INT", + "links": [ + 472 + ] + } + ], + "title": "Max frames", + "properties": { + "cnr_id": "comfyui-kjnodes", + "ver": "e435e999e4b1a828a6b5f6d8f037e66f4a798324", + "Node name for S&R": "INTConstant" + }, + "widgets_values": [ + 500 + ], + "color": "#1b4669", + "bgcolor": "#29699c" + }, + { + "id": 192, + "type": "WanVideoImageToVideoMultiTalk", + "pos": [ + 2836.906982421875, + -1288.3162841796875 + ], + "size": [ + 349.6015625, + 290 + ], + "flags": {}, + "order": 41, + "mode": 0, + "inputs": [ + { + "name": "vae", + "type": "WANVAE", + "link": 440 + }, + { + "name": "start_image", + "shape": 7, + "type": "IMAGE", + "link": 540 + }, + { + "name": "clip_embeds", + "shape": 7, + "type": "WANVIDIMAGE_CLIPEMBEDS", + "link": 433 + }, + { + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 516 + }, + { + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 517 + } + ], + "outputs": [ + { + "name": "image_embeds", + "type": "WANVIDIMAGE_EMBEDS", + "links": [ + 413 + ] + }, + { + "name": "output_path", + "type": "STRING", + "links": [] + } + ], + "properties": { + "cnr_id": "ComfyUI-WanVideoWrapper", + "ver": "49430f900bf812a1e281560bafafd04c43dfdf13", + "Node name for S&R": "WanVideoImageToVideoMultiTalk" + }, + "widgets_values": [ + 832, + 480, + 81, + 9, + false, + "disabled", + false, + "infinitetalk", + "" + ], + "color": "#322", + "bgcolor": "#533" + }, { "id": 128, "type": "WanVideoSampler", @@ -2104,7 +2061,7 @@ "type": "LATENT", "slot_index": 0, "links": [ - 530 + 550 ] }, { @@ -2134,6 +2091,29 @@ -1, true ] + }, + { + "id": 310, + "type": "Note", + "pos": [ + 2849.673095703125, + -937.4252319335938 + ], + "size": [ + 340.64837646484375, + 183.92144775390625 + ], + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This node makes the sampling into a loop to process all the needed frames. Each window is the same size, if the frame count doesn't divide evenly the audio will be padded with silence and extra frames generated.\n\nBetween each window the frames have to be re-encoded, thus no latents are saved and end result is already decoded.\n\nYou can also set an output_path to save each window's result as images during the process." + ], + "color": "#432", + "bgcolor": "#653" } ], "links": [ @@ -2209,14 +2189,6 @@ 2, "WANVIDEOTEXTEMBEDS" ], - [ - 438, - 242, - 0, - 130, - 0, - "WANVAE" - ], [ 440, 244, @@ -2289,14 +2261,6 @@ 0, "*" ], - [ - 493, - 130, - 0, - 131, - 0, - "IMAGE" - ], [ 494, 283, @@ -2361,14 +2325,6 @@ 6, "INT" ], - [ - 530, - 128, - 0, - 130, - 1, - "LATENT" - ], [ 538, 281, @@ -2424,6 +2380,22 @@ 302, 1, "AUDIO" + ], + [ + 550, + 128, + 0, + 309, + 0, + "LATENT" + ], + [ + 551, + 309, + 0, + 131, + 0, + "IMAGE" ] ], "groups": [ @@ -2470,13 +2442,13 @@ "config": {}, "extra": { "ds": { - "scale": 0.6115909044842021, + "scale": 0.6727499949326234, "offset": [ - -305.72724541367705, - 2418.5059970103503 + -916.8927060576216, + 2084.4270316397833 ] }, - "frontendVersion": "1.26.6", + "frontendVersion": "1.27.0", "node_versions": { "ComfyUI-WanVideoWrapper": "0a11c67a0c0062b534178920a0d6dcaa75e7b5fe", "comfy-core": "0.3.43", diff --git a/multitalk/nodes.py b/multitalk/nodes.py index dd2da93..b305237 100644 --- a/multitalk/nodes.py +++ b/multitalk/nodes.py @@ -6,6 +6,7 @@ import torch from ..utils import log, set_module_tensor_to_device import os import json +import datetime script_directory = os.path.dirname(os.path.abspath(__file__)) folder_paths.add_model_folder_path("wav2vec2", os.path.join(folder_paths.models_dir, "wav2vec2")) @@ -389,17 +390,19 @@ class WanVideoImageToVideoMultiTalk: "auto", "multitalk", "infinitetalk" - ], {"default": "auto", "tooltip": "The sampling strategy to use in the long video generation loop, should match the model used"}) + ], {"default": "auto", "tooltip": "The sampling strategy to use in the long video generation loop, should match the model used"}), + "output_path": ("STRING", {"default": "", "tooltip": "If set, will save each window's resulting frames to this folder"}), + } } - RETURN_TYPES = ("WANVIDIMAGE_EMBEDS",) - RETURN_NAMES = ("image_embeds",) + RETURN_TYPES = ("WANVIDIMAGE_EMBEDS", "STRING",) + RETURN_NAMES = ("image_embeds", "output_path") FUNCTION = "process" CATEGORY = "WanVideoWrapper" DESCRIPTION = "Enables Multi/InfiniteTalk long video generation sampling method, the video is created in windows with overlapping frames. Not compatible or necessary to be used with context windows and many other features besides Multi/InfiniteTalk." - def process(self, vae, width, height, frame_window_size, motion_frame, force_offload, colormatch, start_image=None, tiled_vae=False, clip_embeds=None, mode="multitalk"): + def process(self, vae, width, height, frame_window_size, motion_frame, force_offload, colormatch, start_image=None, tiled_vae=False, clip_embeds=None, mode="multitalk", output_path=""): H = height W = width @@ -416,6 +419,11 @@ class WanVideoImageToVideoMultiTalk: target_shape = (16, (num_frames - 1) // VAE_STRIDE[0] + 1, height // VAE_STRIDE[1], width // VAE_STRIDE[2]) + + if output_path: + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + output_path = os.path.join(output_path, f"{timestamp}_{mode}_output") + os.makedirs(output_path, exist_ok=True) image_embeds = { "multitalk_sampling": True, @@ -430,10 +438,11 @@ class WanVideoImageToVideoMultiTalk: "target_shape": target_shape, "clip_context": clip_embeds.get("clip_embeds", None) if clip_embeds is not None else None, "colormatch": colormatch, - "multitalk_mode": mode + "multitalk_mode": mode, + "output_path": output_path } - return (image_embeds,) + return (image_embeds, output_path) NODE_CLASS_MAPPINGS = { "MultiTalkModelLoader": MultiTalkModelLoader, diff --git a/nodes.py b/nodes.py index a44d710..7fc6d20 100644 --- a/nodes.py +++ b/nodes.py @@ -5,6 +5,7 @@ import numpy as np from tqdm import tqdm import inspect import copy +from PIL import Image import hashlib from diffusers.schedulers import FlowMatchEulerDiscreteScheduler @@ -3391,6 +3392,9 @@ class WanVideoSampler: if original_images is None: original_images = torch.zeros([noise.shape[0], 1, target_h, target_w], device=device) + output_path = image_embeds.get("output_path", "") + img_counter = 0 + if len(multitalk_embeds['audio_features'])==2 and (multitalk_embeds['ref_target_masks'] is None): face_scale = 0.1 x_min, x_max = int(target_h * face_scale), int(target_h * (1 - face_scale)) @@ -3746,7 +3750,17 @@ class WanVideoSampler: videos = torch.stack(cm_result_list, dim=0).permute(3, 0, 1, 2) - # cache generated samples + # optionally save generated samples to disk + if output_path: + video_np = videos.clamp(-1.0, 1.0).add(1.0).div(2.0).mul(255).cpu().float().numpy().transpose(1, 2, 3, 0).astype('uint8') + num_frames_to_save = video_np.shape[0] if is_first_clip else video_np.shape[0] - cur_motion_frames_num + log.info(f"Saving {num_frames_to_save} generated frames to {output_path}") + start_idx = 0 if is_first_clip else cur_motion_frames_num + for i in range(start_idx, video_np.shape[0]): + im = Image.fromarray(video_np[i]) + im.save(os.path.join(output_path, f"frame_{img_counter:05d}.png")) + img_counter += 1 + gen_video_list.append(videos if is_first_clip else videos[:, cur_motion_frames_num:]) current_condframe_index += 1 diff --git a/nodes_utility.py b/nodes_utility.py index bb4e408..bbb195d 100644 --- a/nodes_utility.py +++ b/nodes_utility.py @@ -448,6 +448,26 @@ class NormalizeAudioLoudness: normalized_audio = pyloudnorm.normalize.loudness(audio_array, loudness, lufs) return normalized_audio +class WanVideoPassImagesFromSamples: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "samples": ("LATENT",), + } + } + + RETURN_TYPES = ("IMAGE",) + RETURN_NAMES = ("images",) + FUNCTION = "decode" + CATEGORY = "WanVideoWrapper" + DESCRIPTION = "Gets possible already decoded images from the samples dictionary, used with Multi/InfiniteTalk sampling" + + def decode(self, samples): + video = samples.get("video", None) + video.clamp_(-1.0, 1.0) + video.add_(1.0).div_(2.0) + return video.cpu().float(), + NODE_CLASS_MAPPINGS = { "WanVideoImageResizeToClosest": WanVideoImageResizeToClosest, "WanVideoVACEStartToEndFrame": WanVideoVACEStartToEndFrame, @@ -457,7 +477,8 @@ NODE_CLASS_MAPPINGS = { "WanVideoLatentReScale": WanVideoLatentReScale, "CreateScheduleFloatList": CreateScheduleFloatList, "WanVideoSigmaToStep": WanVideoSigmaToStep, - "NormalizeAudioLoudness": NormalizeAudioLoudness + "NormalizeAudioLoudness": NormalizeAudioLoudness, + "WanVideoPassImagesFromSamples": WanVideoPassImagesFromSamples, } NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoImageResizeToClosest": "WanVideo Image Resize To Closest", @@ -468,5 +489,6 @@ NODE_DISPLAY_NAME_MAPPINGS = { "WanVideoLatentReScale": "WanVideo Latent ReScale", "CreateScheduleFloatList": "Create Schedule Float List", "WanVideoSigmaToStep": "WanVideo Sigma To Step", - "NormalizeAudioLoudness": "Normalize Audio Loudness" + "NormalizeAudioLoudness": "Normalize Audio Loudness", + "WanVideoPassImagesFromSamples": "WanVideo Pass Images From Samples", } \ No newline at end of file