Extensions/ComfyUI-VideoHelper-Adv
ComfyUI Extension

ComfyUI-VideoHelper-Adv

Hardened video workflow nodes for ComfyUI with safer output, metadata, and path handling

By rookiestar28·Created 7 months ago·Updated 12 days ago· 14
rookiestar28/ComfyUI-VideoHelper-Adv
Nodes40
On cloudLocal install
CategoryVideo Helper Suite 🎥🅥🅗🅢/audio, Video Helper Suite 🎥🅥🅗🅢
Stars14
Updated12 days ago

Nodes (40)

Audio to legacy VHS_AUDIO🎥🅥🅗🅢

Audio to legacy VHS_AUDIO

Video Helper Suite 🎥🅥🅗🅢/audio
Meta Batch Manager 🎥🅥🅗🅢

Process very long videos without running out of RAM

Video Helper Suite 🎥🅥🅗🅢
Repeat Images 🎥🅥🅗🅢

Repeat Images

Video Helper Suite 🎥🅥🅗🅢/image
Repeat Latents 🎥🅥🅗🅢

Repeat Latents

Video Helper Suite 🎥🅥🅗🅢/latent
Repeat Masks 🎥🅥🅗🅢

Repeat Masks

Video Helper Suite 🎥🅥🅗🅢/mask
Get Image Count 🎥🅥🅗🅢

Get Image Count

Video Helper Suite 🎥🅥🅗🅢/image
Get Latent Count 🎥🅥🅗🅢

Get Latent Count

Video Helper Suite 🎥🅥🅗🅢/latent
Get Mask Count 🎥🅥🅗🅢

Get Mask Count

Video Helper Suite 🎥🅥🅗🅢/mask
Load Audio (Path)🎥🅥🅗🅢

Load an audio file from any path with seek and duration

Video Helper Suite 🎥🅥🅗🅢/audio
Load Audio (Upload)🎥🅥🅗🅢

Drop in an audio file with start and duration

Video Helper Suite 🎥🅥🅗🅢/audio
Load Image (Path) 🎥🅥🅗🅢

Load one image from any path, optionally as a latent

Video Helper Suite 🎥🅥🅗🅢
Load Images (Upload) 🎥🅥🅗🅢

Upload a folder of frames as an image batch

Video Helper Suite 🎥🅥🅗🅢
Load Images (Path) 🎥🅥🅗🅢

Load a folder of frames as an image batch

Video Helper Suite 🎥🅥🅗🅢
Load Video (Upload) 🎥🅥🅗🅢

Get a video file into ComfyUI as frames

Video Helper Suite 🎥🅥🅗🅢
Load Video FFmpeg (Upload) 🎥🅥🅗🅢

Upload a video and load it fast, with alpha

Video Helper Suite 🎥🅥🅗🅢
Load Video FFmpeg (Path) 🎥🅥🅗🅢

Faster video loading with transparency and seek

Video Helper Suite 🎥🅥🅗🅢
Load Video (Path) 🎥🅥🅗🅢

Pull a video into ComfyUI as frames

Video Helper Suite 🎥🅥🅗🅢
Merge Images 🎥🅥🅗🅢

Concatenate two frame batches, resizing if they don't match

Video Helper Suite 🎥🅥🅗🅢/image
Merge Latents 🎥🅥🅗🅢

Join two latent batches, rescaling mismatches

Video Helper Suite 🎥🅥🅗🅢/latent
Merge Masks 🎥🅥🅗🅢

Merge Masks

Video Helper Suite 🎥🅥🅗🅢/mask
Prune Outputs 🎥🅥🅗🅢

Auto-delete the junk files Video Combine leaves behind

Video Helper Suite 🎥🅥🅗🅢
Select Every Nth Image 🎥🅥🅗🅢

Thin a frame batch down by a fixed interval

Video Helper Suite 🎥🅥🅗🅢/image
Select Every Nth Latent 🎥🅥🅗🅢

Thin a latent batch by a fixed interval

Video Helper Suite 🎥🅥🅗🅢/latent
Select Every Nth Mask 🎥🅥🅗🅢

Select Every Nth Mask

Video Helper Suite 🎥🅥🅗🅢/mask
Select Filename 🎥🅥🅗🅢

Get the output file path out of a Video Combine

Video Helper Suite 🎥🅥🅗🅢
Select Images 🎥🅥🅗🅢

Pick specific frames by index, range, or step

Video Helper Suite 🎥🅥🅗🅢/image
Select Latents 🎥🅥🅗🅢

Select Latents

Video Helper Suite 🎥🅥🅗🅢/latent
Select Latest 🎥🅥🅗🅢

Select Latest

Video Helper Suite 🎥🅥🅗🅢
Select Masks 🎥🅥🅗🅢

Select Masks

Video Helper Suite 🎥🅥🅗🅢/mask
Split Images 🎥🅥🅗🅢

Cut a frame batch into two groups at an index

Video Helper Suite 🎥🅥🅗🅢/image
Split Latents 🎥🅥🅗🅢

Split Latents

Video Helper Suite 🎥🅥🅗🅢/latent
Split Masks 🎥🅥🅗🅢

Split Masks

Video Helper Suite 🎥🅥🅗🅢/mask
Unbatch 🎥🅥🅗🅢

Unbatch

Video Helper Suite 🎥🅥🅗🅢
VAE Decode Batched 🎥🅥🅗🅢

VAE Decode Batched

Video Helper Suite 🎥🅥🅗🅢/batched nodes
VAE Encode Batched 🎥🅥🅗🅢

Encode images to latents in controlled batch sizes

Video Helper Suite 🎥🅥🅗🅢/batched nodes
Legacy VHS_AUDIO to Audio🎥🅥🅗🅢

Legacy VHS_AUDIO to Audio

Video Helper Suite 🎥🅥🅗🅢/audio
Video Combine 🎥🅥🅗🅢

Turn a frame batch into an actual video file

Video Helper Suite 🎥🅥🅗🅢
Video Info 🎥🅥🅗🅢

Read fps, frame count, and dimensions out of a loaded video

Video Helper Suite 🎥🅥🅗🅢
Video Info (Loaded) 🎥🅥🅗🅢

The post-load fps, frames, and size, minus the clutter

Video Helper Suite 🎥🅥🅗🅢
Video Info (Source) 🎥🅥🅗🅢

Video Info (Source)

Video Helper Suite 🎥🅥🅗🅢
Readme

ComfyUI-VideoHelper-Adv

Video workflow nodes for ComfyUI, based on Kosinkadink/ComfyUI-VideoHelperSuite.

This fork keeps the upstream VHS node surface compatible where practical, while focusing on safer output behavior, stricter format validation, more predictable preview/output metadata, explicit filesystem trust boundaries, and repo-appropriate automated tests.

<details><summary><h2>Latest Updates - Click to expand</h2></summary> <details> <summary><strong>3.0.0: Workflow input validation, frontend fixes, and stricter checks</strong></summary>

This release contains breaking changes; see the last two items.

  • Video Combine validates every format option against the selected format before encoding: choices must belong to that format, numbers must be within range, and free-text values must be simple tokens that never reach FFmpeg filters. Inputs a format does not declare are ignored.
  • Format names resolve only through the discovered format definitions, including nested custom formats.
  • Upload and media-list loaders authorize the selected name before touching the filesystem, and report missing and out-of-scope names with the same message.
  • Folder previews escape listed file names, Prune Outputs only accepts filenames linked from a node that outputs them, and URL downloads ignore downloader user configuration and fetch a single item.
  • Preview and widget fixes: aspect-ratio changes and same-name re-uploads refresh the preview, stale video metadata responses are ignored, VHS_Unbatch type cloning works inside subgraphs, the path dialog handles keyboard and centering edge cases, unknown latent preview frames are ignored, and integer widgets without a step round correctly.
  • Asset uploads use a route that also works on older frontends without a second upload attempt.
  • Repository checks also catch whitespace errors in staged and committed changes, report setup errors with a consistent exit code, and ship the hook scripts as executable.
  • Breaking: VHS_PATH_POLICY=legacy_local has been removed and now stops the node pack from loading; use allowlist with VHS_EXTERNAL_READ_ROOTS.
  • Breaking: the deprecated manual_format_widgets input is rejected, and saved format values outside the rules above must be updated.
</details> <details> <summary><strong>2.1.0: Host and frontend compatibility improvements</strong></summary>
  • Uploads, feature discovery, path selection, and metadata queries now use ComfyUI's public request transport, preserving host authentication and workspace context. Upload activity stays visible when byte progress is unavailable.
  • Single-file uploads accept safe canonical Asset loader paths, with compatible handling of older responses. Successful or uncertain writes are not replayed.
  • Image-sequence folder uploads preserve subfolders, filenames, and ordering instead of flattening the sequence into Asset tags.
  • Saved-video workflow imports preserve filename and import context, including legacy WebM/MKV metadata, while native media handling remains available.
  • Saved widget values survive frontend configuration migrations, including keyed, named, and positional values and explicit false, 0, or empty values.
  • Supported animated latent previews encode RGB JPEG safely; unsupported decoder lifecycles remain under ComfyUI's own previewer.
  • Compatibility follows public host contracts rather than an exact frontend bundle version. Workflow restoration was checked in both Canvas and Nodes 2.0/Vue.
</details> <details> <summary><strong>Filesystem, URL, and metadata-query boundaries hardened</strong></summary>
  • Media reads, directory listings, previews, output writes, and artifact deletes now pass through one canonical capability policy with safer host-root defaults.
  • Explicit deployment, external-read allowlist, and HTTPS URL modes now fail closed when their configuration is contradictory or unsafe for the active listen posture. (The legacy-local mode added alongside them was removed in 3.0.0.)
  • URL downloads reject credential-bearing, non-HTTPS, and private-address targets before launch, then require bounded results to remain inside ComfyUI temp.
  • Video metadata queries now use a bounded, file-state-aware cache that reauthorizes both hits and stores instead of retaining unbounded stale path data.
</details> <details> <summary><strong>Frontend and core compatibility paths refreshed</strong></summary>
  • Removed deprecated frontend-internal imports and kept the extension on supported ComfyUI entry points, including Desktop bridge-present and bridge-absent loading.
  • Split the largest backend encode/output flow and frontend extension core into focused modules while preserving node IDs, imports, workflow behavior, and extension registration ownership.
  • Format widgets now reconcile against backend-published schemas without deleting linked inputs or depending on private frontend configuration mutation.
  • Select Latest remains a frontend-virtual workflow node with a safe backend rejection; missing or denied paths clear stale target widgets.
  • Removed unreachable clipboard video-blob and nonexistent-node branches while preserving the supported copied-output-path paste interaction.
</details> <details> <summary><strong>Output execution and filter handling made more deterministic</strong></summary>
  • Lazy-loaded audio inputs are preserved through output execution, and audio mux completion returns the final muxed artifact rather than a silent intermediate.
  • Metadata-enabled audio outputs retain round-trip workflow metadata, while metadata-disabled outputs suppress prompt/workflow data in both video tags and the utility PNG sidecar.
  • Repeated simple FFmpeg filters remain supported; unsupported mixed -filter_complex plus -vf/-af configurations now fail clearly before launch.
  • Image-sequence results, partial-output cleanup, prune validation, filename dimensions, and completed-output preview routing remain covered as concrete output contracts.
</details> <details> <summary><strong>Validation and guarded Registry publishing</strong></summary>
  • Added repository-local Python, JavaScript syntax, Node helper, video-format, and diff gates with native Windows and Linux entry points.
  • Added an owned, workspace-contained ComfyUI runtime matrix for output behavior, plus focused path-policy and deferred-path matrices that start and stop only their own loopback hosts.
  • Added least-privilege hosted validation for Ubuntu/Python 3.10 and 3.12 plus Windows/Python 3.12, using Node.js 20 for frontend helper checks.
  • Registry publishing runs when a push to main changes the version in pyproject.toml; pushes without a version change do not publish a new version. Metadata, package contents, publisher ownership, and credential presence are checked first.
  • Manual dispatch supports preflight and publish recovery. Recovery requires main, its exact approved commit, and a matching node/version confirmation; a version tag is not required.
</details> </details>

Table of Contents


What This Fork Improves Over Upstream

The fork began with reliability and save-path hardening around VHS_VideoCombine and now also owns explicit security, compatibility, and validation boundaries:

| Area | Upstream behavior risk | This fork | |---|---|---| | FFmpeg completion | A spawned ffmpeg process could appear successful even when it exited non-zero or did not create the expected file. | Encode completion checks both process return code and expected output existence before returning a result. | | Early failures | Some validation failures could happen after a utility PNG or partial output was already written. | Predictable validation runs before durable artifact creation where possible; failures after writing clean up partial artifacts inside output/temp roots. | | Audio/container compatibility | Missing audio_pass could fall back to implicit Opus args even for incompatible outputs. | Audio support is explicit. Built-in formats declare supports_audio, and unsupported audio + format combinations fail early with a clear error. | | Metadata privacy | save_metadata=false could still leave prompt/workflow metadata in the VHS utility PNG sidecar. | save_metadata=false suppresses prompt/workflow metadata in both video metadata and the utility PNG sidecar. CreationTime may remain. | | Image sequence outputs | %03d image-sequence outputs were represented as the pattern path rather than the actual generated frames. | VHS_FILENAMES contains concrete generated frame paths, and VHS_PruneOutputs understands expanded sequence outputs. | | Prune safety | Prune behavior assumed at most three paths and could delete before discovering an invalid later path. | Prune classifies utility/intermediate/final artifacts, supports expanded sequences, deduplicates candidates, and validates all paths before deleting. | | Filename templates | VideoCombine did not pass dimensions into ComfyUI's save helper, so %width% and %height% resolved to 0. | filename_prefix dimension tokens resolve from the first frame dimensions. | | Preview routing | Completed output preview routing has been aligned to avoid showing stale input-only previews for completed outputs. | Preview helper tests cover advanced routing states. | | Lazy audio | Lazy audio objects could be treated as absent before their waveform was materialized. | Audio presence is preserved through lazy evaluation and verified on the final muxed output. | | Frontend compatibility | Deprecated or private frontend internals create breakage as ComfyUI and Desktop evolve. | Production modules use public ComfyUI request/extension entry points, backend-published format contracts, and widget restoration across frontend migrations. | | Upload paths and replay | Asset response changes or lost directory structure can select the wrong media; retries after uncertain writes can duplicate uploads. | Safe canonical loader paths, compatible older responses, path-preserving folder uploads, and no replay after successful or uncertain writes. | | Saved-video imports | Dropping import context or loading a workflow twice can disrupt restoration. | Legacy workflow imports retain filename/source context and load once; native media handling preserves its original call behavior. | | Animated previews | Four-channel decoded images cannot be encoded directly as JPEG, and decoder lifecycles vary. | Supported image/factor previews produce RGB JPEG; unsupported previewers retain host ownership. | | Filesystem and URL access | Path reads, previews, URL downloads, writes, and deletes can drift into inconsistent trust rules. | One canonical capability policy defaults reads to ComfyUI host roots, keeps writes/deletes in output or temp, and disables URL loading by default for remote-restricted deployments. | | Metadata queries | An unbounded path-keyed metadata cache could retain stale or no-longer-authorized results. | Query metadata uses a bounded LRU with current authorization and file-state checks on every boundary. | | Tests and validation | Upstream is primarily plugin/runtime driven. | This fork adds local and hosted unit/static gates, format validation, Node helper tests, owned live-host matrices, and deterministic release-package inspection. |

Installation

Install this fork into ComfyUI's custom_nodes directory:

cd ComfyUI/custom_nodes
git clone https://github.com/rookiestar28/ComfyUI-VideoHelper-Adv.git
cd ComfyUI-VideoHelper-Adv
python -m pip install -r requirements.txt

Use the same Python interpreter or environment that starts ComfyUI. Restart ComfyUI after installation.

Runtime requirements:

  • opencv-python
  • imageio-ffmpeg
  • av
  • psutil
  • ffmpeg available through imageio-ffmpeg, the repo path, or the system PATH
  • gifski is optional and only needed for gifski-based GIF output

Main Nodes

Load Video

Converts a video file into image frames, frame count, audio, and video info.

Common controls:

  • force_rate: duplicates or drops frames to target a frame rate; 0 disables it.
  • force_size: quickly resizes to common dimensions while preserving aspect ratio where applicable.
  • frame_load_cap: maximum frames returned.
  • skip_first_frames: skips frames after frame-rate adjustment.
  • select_every_nth: samples every Nth source frame without frame duplication.

Both upload and path variants are available. FFmpeg-based variants also expose mask/alpha behavior where supported.

Load Image Sequence

Loads all supported images from a directory into an image batch, with controls similar to Load Video:

  • image_load_cap
  • skip_first_images
  • select_every_nth

Upload and path variants are available. Folder uploads preserve the selected subfolder, original filenames, and deterministic file order. They use the path-preserving upload route even when single-file Asset uploads are available.

Video Combine

Combines an image batch into a video, GIF, WebP, or image sequence. Optional audio can be muxed only when the selected output format explicitly supports audio.

Important inputs:

  • frame_rate: output playback frame rate.
  • loop_count: additional repeats for animated image outputs.
  • filename_prefix: output prefix. Subfolders and ComfyUI format tokens are supported, including %date:*%, %width%, and %height%.
  • format: output format from video_formats/*.json or built-in image formats.
  • pingpong: plays frames forward and then backward for loopable motion.
  • save_output: writes to ComfyUI output when true, or temp when false.
  • save_metadata: when available for the selected video format, controls prompt/workflow metadata in the output video and VHS utility PNG sidecar.

Video Combine returns VHS_FILENAMES: (save_output, output_paths).

  • The list contains full paths for generated artifacts in creation/final-output order.
  • For audio outputs, the final muxed file is returned instead of exposing the silent intermediate as the final result.
  • For image-sequence formats such as 8bit-png and 16bit-png, the list contains the actual generated frame paths, not only the %03d pattern.

Workflow extra options still apply:

  • VHS_MetadataImage=false: do not write the utility PNG sidecar.
  • VHS_KeepIntermediate=false: remove true intermediate artifacts while preserving final artifacts.

When workflow metadata is saved in a supported video container, opening or dropping that video into ComfyUI can restore the graph. The import adapter keeps the filename and import context, supports legacy MP4/WebM/MKV metadata, and delegates videos without a usable embedded workflow to ComfyUI's native handling.

Prune Outputs

Deletes selected outputs from a VHS_FILENAMES result.

Options:

  • Intermediate: delete true intermediate processing files.
  • Intermediate and Utility: also delete the utility PNG sidecar.
  • All: delete utility, intermediate, and final artifacts.

This fork validates all prune candidates are inside ComfyUI output/temp roots before deleting anything, and handles expanded image-sequence frame lists. filenames must be linked from a node that outputs VHS_FILENAMES; a typed or pasted literal value is rejected during prompt validation.

Audio Nodes

  • Load Audio (Path)
  • Load Audio (Upload)
  • legacy VHS_AUDIO conversion helpers

Batch, Info, and Utility Nodes

The fork keeps the upstream batch and utility nodes, including:

  • Meta Batch Manager
  • Video Info / Video Info Source / Video Info Loaded
  • Select Filename / Select Latest
  • VAE Encode Batched / VAE Decode Batched
  • Split, merge, repeat, select, and count helpers for images, masks, and latents
  • Unbatch

Select Latest is a frontend-virtual helper: ComfyUI applies its selected path to connected widgets before queue submission. Direct backend/API submission of that helper fails safely instead of executing as a path-reading node.

Video Previews

Load Video, Load Images, and Video Combine provide previews.

Preview context menu actions include:

  • Open preview
  • Save preview
  • Pause preview
  • Hide preview
  • Sync preview

Advanced Previews

Advanced Previews can be enabled in ComfyUI settings through VHS Advanced Previews. When enabled, preview routes can transcode or downscale media for browser-friendly display.

Benefits:

  • Load Video previews can reflect node settings such as skipped frames and load caps.
  • Remote browser bandwidth can be reduced.
  • Browser performance can improve for large or normally unsupported media.
  • The backend path policy applies the same authorization to previews as to node loads.

Tradeoffs:

  • Preview generation can add delay for long inputs.
  • Generated previews are lower quality than the original media; use Open preview for the source artifact.

Animated Latent Previews

Enable VHS.LatentPreview in ComfyUI settings to show animated sampling previews for supported host image/factor previewers. VHS.LatentPreviewRate controls the playback rate; 0 retains the host latent format's automatic default. This rate does not change the output video's frame rate.

JPEG preview frames are encoded as RGB, including when an image decoder returns four channels. Unknown, temporal, or compile-aware previewers keep ComfyUI's original behavior; enabling this setting does not add support for every model or decoder. Preview targeting also handles nodes inside subgraphs.

Filesystem and URL Security Policy

The default filesystem mode is host_roots. Media reads, directory listings, and previews are limited to ComfyUI's input, output, and temp roots. Writes and deletes are always limited to output and temp, including when an external read root is configured.

Server environment options:

  • VHS_PATH_POLICY=host_roots|allowlist selects the filesystem mode. The former legacy_local mode has been removed; setting it stops the node pack from loading with a configuration error. Use allowlist with VHS_EXTERNAL_READ_ROOTS to read media from additional directories.
  • VHS_EXTERNAL_READ_ROOTS is an OS-path-separator-delimited list of existing directories. It is required by allowlist, rejected in other modes, and grants read/list/preview capabilities only.
  • VHS_DEPLOYMENT_PROFILE=trusted_local|remote_restricted may make the derived deployment profile more restrictive. A non-loopback or unknown listen address cannot be overridden to trusted_local.
  • VHS_URL_POLICY=disabled|https controls URL-backed media loading. Its default is https for loopback-only trusted-local operation and disabled for a remote-restricted deployment.

VHS_STRICT_PATHS is a temporary deprecated alias. During its compatibility window, any value maps to host_roots, and it must not be combined with VHS_PATH_POLICY. The alias is scheduled for removal in the next breaking release after the first public release containing this policy.

Upload-list names used by Load Video, Load Video FFmpeg, Load Audio (Upload), and Load Images resolve inside one host root: input by default, or the root named by a trailing [input], [output], or [temp] annotation. Subfolders are allowed. Absolute, drive-qualified, .., and control-character names are rejected before any filesystem check, and a missing name and an unauthorized name return the same validation message.

HTTPS URL loading rejects credentials, fragments, non-HTTPS schemes, and non-public resolved IP addresses before launching the downloader. Downloads are time/size bounded and their results must resolve inside ComfyUI temp. Redirect and DNS-rebinding behavior in the external downloader remains a residual network risk; keep URL loading disabled for LAN, proxy, public, or multi-user deployments unless that risk is separately isolated and accepted.

Video Formats

Video formats are JSON files under video_formats/ or the ComfyUI VHS_video_formats folder. They describe ffmpeg args and optional UI widgets.

Example:

{
  "main_pass": [
    "-n",
    "-c:v", "libsvtav1",
    "-pix_fmt", "yuv420p10le",
    "-crf", ["crf", "INT", {"default": 23, "min": 0, "max": 100, "step": 1}]
  ],
  "audio_pass": ["-c:a", "libopus"],
  "supports_audio": true,
  "save_metadata": ["save_metadata", "BOOLEAN", {"default": true}],
  "extension": "webm",
  "environment": {"SVT_LOG": "1"}
}

Key fields:

  • main_pass: ffmpeg arguments used for the main video/image encode.
  • audio_pass: ffmpeg audio args used only when audio is connected.
  • supports_audio: must be true when the format supports audio, or false for formats that must reject audio.
  • save_metadata: exposes metadata saving as a widget for supported video formats.
  • extension: output file extension and container hint.
  • environment: optional environment variables for the ffmpeg process.
  • input_color_depth: 8bit or 16bit.
  • dim_alignment: optional output dimension alignment requirement.

Format widget values are validated against the selected format before any output is written: combo values must be one of that format's choices, INT and FLOAT values must be numbers within the declared min/max, and BOOLEAN values must be booleans. A STRING widget must be a single token of letters, digits, _, ., +, or - that does not start with -, and it cannot be used inside an ffmpeg filter argument (-vf, -af, -lavfi, -filter_complex); use a combo or numeric widget there instead. The deprecated manual_format_widgets input is no longer accepted; pass format widget values as regular inputs.

Repeated simple -vf or -af filters are merged. A format that mixes -filter_complex with an additional simple filter is rejected explicitly; arbitrary filter-graph composition is not inferred automatically.

Validate format files after editing:

python scripts/validate_video_formats.py

Testing This Fork

This repository is a ComfyUI custom node repo, not a standalone web app or npm package. It intentionally has no package.json, npm test, repo-managed Playwright dependency/browser installation, or .pre-commit-config.yaml.

Install test tooling into a repository-local .venv from requirements-test.txt. The wrappers below require that local environment and Node.js 18 or newer.

# Windows
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements-test.txt
# Linux / Git Bash
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-test.txt

Windows PowerShell:

powershell -NoProfile -File scripts/run_repo_checks.ps1

Linux or Git Bash:

bash scripts/run_pre_push_checks.sh

Both wrappers delegate to the same repository check runner and execute:

  • Python compile checks
  • Python unit tests through scripts/run_unittests.py
  • JavaScript syntax checks for web/js/*.js
  • Node built-in helper tests under tests/js/
  • all video_formats/*.json schema checks
  • whitespace checks with git diff --check for unstaged and staged changes, plus the committed range since a base when one is given

To also check commits that are not on main yet, pass a base through either wrapper or set VHS_DIFF_CHECK_BASE:

powershell -NoProfile -File scripts/run_repo_checks.ps1 --diff-base main

A base that is not a reachable commit stops the run with exit code 2, the same code used for a missing .venv or an unsupported Node.js version.

The same contract runs in .github/workflows/validate.yml on Ubuntu with Python 3.10/3.12 and Windows with Python 3.12. Its whitespace base is the pull request base, the previous main commit for pushes to main, or origin/main for other branch pushes. Hosted validation is publication-incapable.

Additional useful checks:

python scripts/validate_video_formats.py
python scripts/probe_video_format_outputs.py
python -m unittest tests.test_runtime_validation_matrix

Live behavior uses owned, workspace-contained ComfyUI processes. Point these commands at a trusted ComfyUI checkout and the Python interpreter that can run that host; do not point them at an unreviewed reference checkout.

Run all eight output scenarios:

python scripts/runtime/run_runtime_matrix.py \
  --comfyui-root <TRUSTED_COMFYUI_ROOT> \
  --comfyui-python <TRUSTED_COMFYUI_PYTHON> \
  --all

Run the filesystem/URL policy matrix:

python scripts/runtime/run_path_policy_matrix.py \
  --comfyui-root <TRUSTED_COMFYUI_ROOT> \
  --comfyui-python <TRUSTED_COMFYUI_PYTHON>

Run the focused virtual-node, cache, and FFmpeg-filter matrix:

python scripts/runtime/run_deferred_paths_matrix.py \
  --comfyui-root <TRUSTED_COMFYUI_ROOT> \
  --comfyui-python <TRUSTED_COMFYUI_PYTHON>

The runners copy the plugin into a disposable workspace-contained layout, listen only on an owned loopback port, stop only their own host, and write content-free result documents under .tmp/runtime_results/. The production UI probe is intentionally separate because this repository does not install or manage a browser dependency.

Compatibility Notes

  • The node names and common workflow shape are kept close to upstream VHS for workflow compatibility.
  • Compatibility uses public host capabilities rather than an exact core/frontend bundle whitelist. Older and newer frontend workflow formats are handled without a version-specific branch.
  • Uploads use the host's public request transport and current advertised features. Authorization errors and uncertain write outcomes are reported without attempting a duplicate upload.
  • Saved widget restoration supports keyed, named, and compact positional values, preserving explicit false, zero, and empty values across frontend migrations.
  • Output behavior is stricter than upstream when it prevents silent corruption, metadata leakage, unsupported audio muxing, or unsafe deletion.
  • External custom video_formats should explicitly declare audio support with supports_audio and audio_pass when audio is intended.
  • Path authorization is enforced by a central, canonical capability policy. External read roots never grant output-write or delete access.
  • The legacy_local filesystem mode has been removed. Deployments that set it must switch to allowlist with explicit VHS_EXTERNAL_READ_ROOTS.
  • Workflows that relied on manual_format_widgets or on free-text format values outside the documented format-widget rules must be updated.
  • URL loading should remain disabled for LAN, reverse-proxy, public, or multi-user deployments unless downloader isolation and residual redirect/DNS risks are accepted separately.
  • This repository has independent versioning, validation, and release safeguards. It does not require an upstream pull request and does not imply that a Registry release has already occurred.