- Added `file_names` to INPUT_TYPES and `current_file_name` to RETURN_TYPES.
- Removed `INPUT_IS_LIST = True` to avoid double nesting in ComfyUI list processing.
- Cleaned up temp files (`test_loop_syntax.py`, test `.sh` scripts).
- Verified `BatchTextFileReader` does not exist in the repository.
- Removed `INPUT_IS_LIST = True` to prevent ComfyUI from implicitly converting input values to lists and expecting lists as outputs.
- Refactored `calculate` to handle list inputs natively using `isinstance` while correctly interacting with the standard Text Reader's native Python lists.
- Changed the return signature to emit native primitive values (`str`, `int`) instead of wrapping them in lists, correctly accommodating downstream integration with TTS models (e.g. Fish Speech) that expect pure strings.
ComfyUI's `INPUT_IS_LIST = True` behavior wraps incoming data in a list. When an upstream node (like `BatchTextFileReader`) already returns a list, ComfyUI wraps it again, creating a list of lists (e.g., `[["file1", "file2"]]`).
This patch updates `AutoLoopCalculatorTTSBatch.calculate` to robustly detect and unpack this double-wrapping before extracting the target texts, preventing a downstream `AttributeError` during string manipulation.
- Added global tracking variables (`global_batch_index`, `global_has_more_batches`, `global_is_batch_advancing`) to `loop.py` to maintain batch state
- Updated `SequentialLoopStart` reset logic to prevent loop index reset on automatic batch advances
- Implemented the `AutoLoopCalculatorTTSBatch` node with `INPUT_IS_LIST = True` returning list-wrapped chunks to bypass native ComfyUI parallelization
- Updated `SequentialLoopTrigger` requeue logic to handle batch completion correctly using `reset_loop=True` with `loop_idx=0` when `has_more_batches` is truthy
The `SequentialLoopTrigger` node was mutating seeds with `0xffffffff`, which exceeded the maximum value for a signed 32-bit integer. This caused a validation error in strict nodes like `OllamaOptionsV2` during loop iterations. This commit lowers the maximum generated random seed value to `0x7fffffff` to remain within safe limits.
Replaces the single `urlopen` call with a resilient retry loop (up to 3 attempts, 10s timeout, 1s delay) when checking the ComfyUI server status. Now raises a strict `RuntimeError` if all attempts fail, halting the execution queue and surfacing the error on the UI.
Added input validations (`source_frame_count <= 0` or `target_frames_per_loop <= 0`) to `AutoLoopCalculatorLTX` (in `loop.py`), and `AutoLoopCalculator`, `AutoLoopCalculatorWan` (in `video.py`). When conditions are met, a safe default is returned to prevent math domain errors. Also included a new comprehensive unit test suite in `tests/test_loop_calculator.py`.
Addresses the missing tests for MasterSwitch node's route and check_lazy_status methods in switch_node.py. Tests verify branching functionality based on is_final_cycle parameter and include edge case checking for None values.
Modified `tools.py` to add an `isinstance` check and raise a `ValueError` when non-tensor input is passed. Also added `test_tools.py` to verify this behavior.
Adds a new ComfyUI utility node `AudioDurationCalculator` to `tools.py` for
calculating the exact duration of an audio file in seconds. Includes robust
error handling to ensure the input is a valid dictionary and returns a
logging string output to maintain consistency with other tools.
- Introduce `global_step_by_chunk` ghost variable initialized to `False` in `loop.py`
- Set `loop.global_step_by_chunk = True` in `AutoLoopCalculatorTTS` to indicate chunk mode
- Reset `loop.global_step_by_chunk = False` in video calculators (`AutoLoopCalculator`, `AutoLoopCalculatorWan`, `AutoLoopCalculatorLTX`) to ensure state resets
- Update `SessionImageSender.send_image` timeline management to branch logic, using `is_chunk_mode` to calculate progress differently for text chunks versus video frames
This commit replaces the raw regex text-splitting logic in `AutoLoopCalculatorTTS` with an "intelligent buffer" approach. It first splits the text by sentence terminators as before, but now aggregates these smaller segments until they contain a minimum of 5 words.
This prevents TTS models from generating robotic, out-of-context micro-audios when encountering trailing ellipses (`...`) or extremely short phrases, leading to more natural intonation and pacing.
All existing loop and timeline injections are preserved.
Replaced simple paragraph/sentence splitting with advanced regex
to gracefully handle split scenarios involving `.`, `?`, `!`,
quotes, ellipses, and `\n`. Punctuation is correctly retained on
the chunks to assure proper TTS intonation.
Moved `import re` to module level imports.
Replaced destructive `del inputs["on_true"]` and `del inputs["on_false"]` with simple state update `inputs["is_final_cycle"] = is_next_final` to rely on MasterSwitch's native lazy evaluation (`check_lazy_status`), fixing a `NodeInputError` bug during looping.
Update `SequentialLoopTrigger` in `loop.py` to correctly identify
`AutoLoopCalculatorTTS` and set `estimated_chunk` to 1 instead of falling
back to a default of 50. This prevents the trigger from incorrectly guessing
when the final loop occurs and mutating the graph prematurely, which caused
errors during sequential TTS tasks.
Refactors `IncrementalVideoStitcher.stitch` to eliminate in-place assignments
into a pre-allocated empty tensor when loading image frames in parallel, which
caused `RuntimeError: Inplace update to inference tensor outside InferenceMode
is not allowed.` in newer PyTorch versions.
The refactored implementation uses a pure map function to return individual
tensors and concatenates them sequentially using `torch.cat`, remaining thread-safe
and compatible with PyTorch's `InferenceMode`. Security against deserialization
vulnerabilities is preserved by ensuring `weights_only=True` remains when loading
audio caches.
- Implemented unit tests for `extract_and_standardize_audio` in `video.py`.
- Added test case to verify exception handling when `torchaudio.load` fails.
- Expanded coverage to include resampling and channel standardization (mono/multichannel to stereo).
- Followed the repository's clean testing pattern for mocking dependencies and loading code under test.
Merged two sequential loops over `prompt.items()` in `SequentialLoopTrigger.trigger_next` into a single pass.
The first pass now simultaneously finds the `estimated_chunk` from `AutoLoopCalculator` and performs mutations for seeds and loop indices.
`MasterSwitch` mutations are deferred to a small secondary pass after `is_next_final` is calculated using the gathered chunk size.
This change reduces the overhead of iterating over large prompt dictionaries and yielded a ~26.8% performance improvement in synthetic benchmarks.
Added `weights_only=True` to `torch.load()` in `video.py` to prevent insecure deserialization and potential arbitrary code execution via crafted pickle files. This change restricts the unpickler to only load tensors, primitive types, and basic containers, which is sufficient for the audio dictionary being loaded.
This commit introduces a new dropdown to the `AutoLoopCalculatorTTS` node inside `video.py`, allowing text to be split by either "Párrafos (Saltos de línea)" or "Frases (Puntos)". When splitting by sentences, it cleanly preserves the periods to maintain proper intonation in TTS systems. Output pins are renamed (`current_text`, `total_chunks`) for better semantics.