rgthree / rgthree-comfy

Making ComfyUI more comfortable!
MIT License
781 stars 64 forks source link

[Feature Request] Video Comparer #139

Open qqqllppp opened 5 months ago

qqqllppp commented 5 months ago

Like image comparer, but instead of a still frames, have the video playback in a loop. Useful to compare upscaled video consistency over time.

rgthree commented 5 months ago

I haven't really been playing with video stuff yet. Do you have a small, example workflow I could try out?

qqqllppp commented 5 months ago

As far as I know there are no video comparer nodes available in comfyui. Here is a code example I found online https://codepen.io/madmax_furycode/details/NWOweoQ

rgthree commented 5 months ago

Sorry, I meant a simple comfyui workflow where you would want the comparer node. (I just haven’t started with video yet, so that will give me a working example)

qqqllppp commented 5 months ago

Here is a super simple workflow where I compare two videos in comfyui @rgthree . The only way to do this effectively with a slider is using the image comparer and manually iterate the index. This current way is very inefficient for video as it only compares 1 frame at a time. A better way would to allow the video to play in a loop via a "video comparer" node while allowing the user to use a slider as well as the video plays. Hope this helps :)

Of course, the video comparer node can be applied to more complex workflows as well like comparing videos generated from AnimateDiff or SVDs.

{
  "last_node_id": 6,
  "last_link_id": 7,
  "nodes": [
    {
      "id": 5,
      "type": "Image Comparer (rgthree)",
      "pos": {
        "0": 1451,
        "1": 346.12841796875,
        "2": 0,
        "3": 0,
        "4": 0,
        "5": 0,
        "6": 0,
        "7": 0,
        "8": 0,
        "9": 0
      },
      "size": {
        "0": 850.3193359375,
        "1": 596.6951293945312
      },
      "flags": {},
      "order": 5,
      "mode": 0,
      "inputs": [
        {
          "name": "image_a",
          "type": "IMAGE",
          "link": 3,
          "dir": 3
        },
        {
          "name": "image_b",
          "type": "IMAGE",
          "link": 4,
          "dir": 3
        }
      ],
      "outputs": [],
      "properties": {
        "comparer_mode": "Slide"
      },
      "widgets_values": [
        [
          "/view?filename=rgthree.compare._temp_kdcmd_00001_.png&type=temp&subfolder=&rand=0.0947206001955625",
          "/view?filename=rgthree.compare._temp_kdcmd_00002_.png&type=temp&subfolder=&rand=0.8569397182028257"
        ]
      ]
    },
    {
      "id": 3,
      "type": "VHS_LoadVideoPath",
      "pos": [
        850,
        350
      ],
      "size": [
        320,
        218
      ],
      "flags": {},
      "order": 0,
      "mode": 0,
      "inputs": [
        {
          "name": "batch_manager",
          "type": "VHS_BatchManager",
          "link": null
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            2
          ],
          "shape": 3,
          "slot_index": 0
        },
        {
          "name": "frame_count",
          "type": "INT",
          "links": null,
          "shape": 3
        },
        {
          "name": "audio",
          "type": "VHS_AUDIO",
          "links": null,
          "shape": 3
        }
      ],
      "properties": {
        "Node name for S&R": "VHS_LoadVideoPath"
      },
      "widgets_values": {
        "video": "/home/video1.mp4",
        "force_rate": 0,
        "force_size": "Disabled",
        "custom_width": 512,
        "custom_height": 512,
        "frame_load_cap": 48,
        "skip_first_frames": 0,
        "select_every_nth": 1,
        "videopreview": {
          "hidden": false,
          "paused": false,
          "params": {
            "frame_load_cap": 48,
            "skip_first_frames": 0,
            "force_rate": 0,
            "filename": "/home/video1.mp4",
            "type": "path",
            "format": "video/mp4",
            "select_every_nth": 1
          }
        }
      }
    },
    {
      "id": 1,
      "type": "VHS_LoadVideoPath",
      "pos": [
        850,
        740
      ],
      "size": [
        320,
        218
      ],
      "flags": {},
      "order": 1,
      "mode": 0,
      "inputs": [
        {
          "name": "batch_manager",
          "type": "VHS_BatchManager",
          "link": null
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            1
          ],
          "shape": 3,
          "slot_index": 0
        },
        {
          "name": "frame_count",
          "type": "INT",
          "links": null,
          "shape": 3
        },
        {
          "name": "audio",
          "type": "VHS_AUDIO",
          "links": null,
          "shape": 3
        }
      ],
      "properties": {
        "Node name for S&R": "VHS_LoadVideoPath"
      },
      "widgets_values": {
        "video": "/home/video2.mp4",
        "force_rate": 0,
        "force_size": "Disabled",
        "custom_width": 512,
        "custom_height": 512,
        "frame_load_cap": 48,
        "skip_first_frames": 0,
        "select_every_nth": 1,
        "videopreview": {
          "hidden": false,
          "paused": false,
          "params": {
            "frame_load_cap": 48,
            "skip_first_frames": 0,
            "force_rate": 0,
            "filename": "/home/video2.mp4",
            "type": "path",
            "format": "video/mp4",
            "select_every_nth": 1
          }
        }
      }
    },
    {
      "id": 2,
      "type": "FromListGet1Image",
      "pos": [
        850,
        630
      ],
      "size": {
        "0": 315,
        "1": 58
      },
      "flags": {},
      "order": 4,
      "mode": 0,
      "inputs": [
        {
          "name": "list",
          "type": "IMAGE",
          "link": 1
        },
        {
          "name": "index",
          "type": "INT",
          "link": 7,
          "widget": {
            "name": "index"
          },
          "slot_index": 1
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            4
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "FromListGet1Image"
      },
      "widgets_values": [
        15
      ]
    },
    {
      "id": 4,
      "type": "FromListGet1Image",
      "pos": [
        860,
        230
      ],
      "size": {
        "0": 315,
        "1": 58
      },
      "flags": {},
      "order": 3,
      "mode": 0,
      "inputs": [
        {
          "name": "list",
          "type": "IMAGE",
          "link": 2
        },
        {
          "name": "index",
          "type": "INT",
          "link": 6,
          "widget": {
            "name": "index"
          },
          "slot_index": 1
        }
      ],
      "outputs": [
        {
          "name": "IMAGE",
          "type": "IMAGE",
          "links": [
            3
          ],
          "shape": 3,
          "slot_index": 0
        }
      ],
      "properties": {
        "Node name for S&R": "FromListGet1Image"
      },
      "widgets_values": [
        15
      ]
    },
    {
      "id": 6,
      "type": "PrimitiveNode",
      "pos": [
        545,
        548
      ],
      "size": {
        "0": 210,
        "1": 82
      },
      "flags": {},
      "order": 2,
      "mode": 0,
      "outputs": [
        {
          "name": "INT",
          "type": "INT",
          "links": [
            6,
            7
          ],
          "widget": {
            "name": "index"
          },
          "slot_index": 0
        }
      ],
      "title": "index",
      "properties": {
        "Run widget replace on values": false
      },
      "widgets_values": [
        15,
        "fixed"
      ]
    }
  ],
  "links": [
    [
      1,
      1,
      0,
      2,
      0,
      "IMAGE"
    ],
    [
      2,
      3,
      0,
      4,
      0,
      "IMAGE"
    ],
    [
      3,
      4,
      0,
      5,
      0,
      "IMAGE"
    ],
    [
      4,
      2,
      0,
      5,
      1,
      "IMAGE"
    ],
    [
      6,
      6,
      0,
      4,
      1,
      "INT"
    ],
    [
      7,
      6,
      0,
      2,
      1,
      "INT"
    ]
  ],
  "groups": [],
  "config": {},
  "extra": {},
  "version": 0.4
}
brandostrong commented 1 week ago

Sorry to resurrect this, but this is something I'd absolutely love. I'm always trying to compare upscaling and visual differences with animatediff runs. Having a slide compare that's synced to the same time for both videos would be magical, even better with seek controls.