diff --git a/pyproject.toml b/pyproject.toml index 937056b..ae4d60b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-videohelpersuite" description = "Nodes related to video workflows" -version = "1.7.2" +version = "1.7.3" license = { file = "LICENSE" } dependencies = ["opencv-python", "imageio-ffmpeg"] diff --git a/tests/audio.json b/tests/audio.json new file mode 100644 index 0000000..cae3d76 --- /dev/null +++ b/tests/audio.json @@ -0,0 +1,313 @@ +{ + "id": "07b812b5-5037-4878-90bc-32d3a1f36619", + "revision": 0, + "last_node_id": 7, + "last_link_id": 5, + "nodes": [ + { + "id": 5, + "type": "VHS_VideoCombine", + "pos": [ + 732, + -23 + ], + "size": [ + 210, + 334 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 2 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 3 + }, + { + "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": { + "Node name for S&R": "VHS_VideoCombine" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "AnimateDiff", + "format": "video/webm", + "pix_fmt": "yuv420p", + "crf": 20, + "save_metadata": true, + "trim_to_audio": false, + "pingpong": false, + "save_output": false, + "videopreview": { + "hidden": false, + "paused": false, + "params": {} + } + } + }, + { + "id": 6, + "type": "VHS_VideoCombine", + "pos": [ + 503, + 363 + ], + "size": [ + 210, + 334 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 4 + }, + { + "name": "audio", + "shape": 7, + "type": "AUDIO", + "link": 5 + }, + { + "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": { + "Node name for S&R": "VHS_VideoCombine" + }, + "widgets_values": { + "frame_rate": 8, + "loop_count": 0, + "filename_prefix": "AnimateDiff", + "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": {} + } + } + }, + { + "id": 4, + "type": "VHS_LoadVideoPath", + "pos": [ + 29, + 16 + ], + "size": [ + 221.27618408203125, + 413.1552734375 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "name": "meta_batch", + "shape": 7, + "type": "VHS_BatchManager", + "link": null + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": null + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 2, + 4 + ] + }, + { + "name": "frame_count", + "type": "INT", + "links": null + }, + { + "name": "audio", + "type": "AUDIO", + "links": [ + 3 + ] + }, + { + "name": "video_info", + "type": "VHS_VIDEOINFO", + "links": null + } + ], + "properties": { + "Node name for S&R": "VHS_LoadVideoPath" + }, + "widgets_values": { + "video": "input/bigbuckbunny.mp4", + "force_rate": 8, + "custom_width": 0, + "custom_height": 0, + "frame_load_cap": 30, + "skip_first_frames": 0, + "select_every_nth": 1, + "format": "AnimateDiff", + "videopreview": { + "hidden": false, + "paused": false, + "params": { + "filename": "input/bigbuckbunny.mp4", + "type": "path", + "format": "video/mp4", + "force_rate": 8, + "custom_width": 0, + "custom_height": 0, + "frame_load_cap": 30, + "skip_first_frames": 0, + "select_every_nth": 1 + } + } + } + }, + { + "id": 7, + "type": "VHS_LoadAudio", + "pos": [ + 83, + 564 + ], + "size": [ + 218.93820190429688, + 126 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "audio", + "type": "AUDIO", + "links": [ + 5 + ] + }, + { + "name": "duration", + "type": "FLOAT", + "links": null + } + ], + "properties": { + "Node name for S&R": "VHS_LoadAudio" + }, + "widgets_values": { + "audio_file": "input/bigbuckbunny.mp4", + "seek_seconds": 0, + "duration": 5 + } + } + ], + "links": [ + [ + 2, + 4, + 0, + 5, + 0, + "IMAGE" + ], + [ + 3, + 4, + 2, + 5, + 1, + "AUDIO" + ], + [ + 4, + 4, + 0, + 6, + 0, + "IMAGE" + ], + [ + 5, + 7, + 0, + 6, + 1, + "AUDIO" + ] + ], + "groups": [], + "config": {}, + "extra": { + "frontendVersion": "1.25.0", + "VHS_latentpreview": true, + "VHS_latentpreviewrate": 0, + "VHS_MetadataImage": true, + "VHS_KeepIntermediate": true + }, + "version": 0.4, + "tests": { + "5": [{"type": "audio", "key": "nb_read_packets", "value": "177"}], + "6": [{"type": "audio", "key": "nb_read_packets", "value": "176"}], + "length": 2 + } +} \ No newline at end of file diff --git a/videohelpersuite/latent_preview.py b/videohelpersuite/latent_preview.py index a9b8757..d30a97b 100644 --- a/videohelpersuite/latent_preview.py +++ b/videohelpersuite/latent_preview.py @@ -13,7 +13,7 @@ serv = server.PromptServer.instance from .utils import hook rates_table = {'Mochi': 24//6, 'LTXV': 24//8, 'HunyuanVideo': 24//4, - 'Cosmos1CV8x8x8': 24//8, 'Wan21': 16//4} + 'Cosmos1CV8x8x8': 24//8, 'Wan21': 16//4, 'Wan22': 24//4} class WrappedPreviewer(latent_preview.LatentPreviewer): def __init__(self, previewer, rate=8): diff --git a/videohelpersuite/server.py b/videohelpersuite/server.py index 4bda173..afb3140 100755 --- a/videohelpersuite/server.py +++ b/videohelpersuite/server.py @@ -149,24 +149,24 @@ async def query_video(request): else: source = {} try: - cont = av.open(filepath) - stream = cont.streams.video[0] - source['fps'] = float(stream.average_rate) - source['duration'] = float(cont.duration / av.time_base) + with av.open(filepath) as cont: + stream = cont.streams.video[0] + source['fps'] = float(stream.average_rate) + source['duration'] = float(cont.duration / av.time_base) - if stream.codec_context.name == 'vp9': - cc = av.Codec('libvpx-vp9', 'r').create() - else: - cc = stream - def fit(): - for packet in cont.demux(video=0): - yield from cc.decode(packet) - frame = next(fit()) + if stream.codec_context.name == 'vp9': + cc = av.Codec('libvpx-vp9', 'r').create() + else: + cc = stream + def fit(): + for packet in cont.demux(video=0): + yield from cc.decode(packet) + frame = next(fit()) - source['size'] = [frame.width, frame.height] - source['alpha'] = 'a' in frame.format.name - source['frames'] = stream.metadata.get('NUMBER_OF_FRAMES', round(source['duration'] * source['fps'])) - query_cache[filepath] = (os.stat(filepath).st_mtime, source) + source['size'] = [frame.width, frame.height] + source['alpha'] = 'a' in frame.format.name + source['frames'] = stream.metadata.get('NUMBER_OF_FRAMES', round(source['duration'] * source['fps'])) + query_cache[filepath] = (os.stat(filepath).st_mtime, source) except Exception: pass if not 'frames' in source: diff --git a/web/js/VHS.core.js b/web/js/VHS.core.js index 5e78170..82a2e9f 100755 --- a/web/js/VHS.core.js +++ b/web/js/VHS.core.js @@ -1702,7 +1702,7 @@ function mouseAnnotated(event, [x, y], node) { break } } - if (node.widgets[++i]?.type == "BOOLEAN") {//restrict to annotatedNUmbers + if (node.widgets[++i]?.type == "VHS.ANNOTATED") {//restrict to annotatedNUmbers node.widgets[i]?.mouse(event, [x, y+24], node) } } @@ -2175,7 +2175,7 @@ app.registerExtension({ return } const s = this.options.step - let sh = this.options.mod ?? 1 + let sh = this.options.mod ?? 0 this.value = Math.round((v - sh) / s) * s + sh }, config: inputData,