Fix Python 3.13 numba and librosa compatibility handling
Technical details:
- Stop forcing NUMBA_DISABLE_JIT at startup on Python 3.13
- Use safe audio loading and resampling in IndexTTS-2 and ChatterBox Official 23-Lang
- Update audio hashing and fallback paths for newer numba stacks
fix: enforce numba.config.DISABLE_JIT when env var already set
- NUMBA_DISABLE_JIT=1 env var has no effect if numba is already imported
- When env var is present, now also set numba.config.DISABLE_JIT=True directly
- Fixes users where NUMBA_DISABLE_JIT was set but crash still occurred
Fix: Use librosa.resample as numba JIT compatibility test instead of stft
- librosa.stft does not trigger librosa.core.audio lazy-load
- librosa.resample does, which is where @guvectorize crashes on NumPy 2.x
- This ensures the startup test actually catches the failure before engines run
Fix: Restore Numba/librosa JIT compatibility test at startup for NumPy 2.x
- Restore full librosa JIT test at startup for NumPy 2.x environments
- PR 262 lazy-import optimization had deferred this test too late, after numba
was already loaded, making NUMBA_DISABLE_JIT ineffective
- NumPy 1.x users still skip the test entirely (zero cost)
- Python 3.13+ still handled by preemptive env var (zero cost)
- Addresses get_call_template AttributeError crash in librosa on affected hardware
Address issue #249: Windows AMD ROCm torch.distributed.ReduceOp compatibility
Technical implementation:
- Add patch_torch_distributed_reduceop() to PyTorchPatches class
- Create stub ReduceOp class when missing from torch.distributed
- Inject stub early in startup before engine imports
- Enables single-GPU inference on Windows AMD ROCm 7.2 builds
This allows bundled engines (Step Audio EditX, Higgs Audio, IndexTTS, etc.) to import successfully even when PyTorch 2.9.1+rocmsdk20260116 has incomplete torch.distributed module.
Add Step Audio EditX Mac (MPS) compatibility patch
Technical details:
- Create centralized device compatibility patch system
- Monkey-patch hardcoded CUDA device calls in upsample_encoder_v2.py
- Detect device from model parameters instead of hardcoding
- Gracefully disable CUDA Graphs on non-CUDA devices (MPS/CPU)
- Apply patch automatically when Step Audio EditX engine loads
Addresses issue #245 (requires Mac user testing)
Fixed 'dict' object has no attribute 'cpu' error when using Voice Designer
voices with TTS Text node.
## Root Cause
Voice Designer and Character Voices nodes output unified NARRATOR_VOICE format:
{
"audio": {"waveform": tensor, "sample_rate": 24000},
"audio_path": "...",
"reference_text": "...",
...
}
But TTS Text node was wrapping this AGAIN when creating voice_mapping:
{
"waveform": audio_tensor, # audio_tensor was already a dict!
"sample_rate": 24000,
"text": "..."
}
This created triple-nested structure that broke audio hashing.
## Fixes Applied
**TTS Text Node** (nodes/unified/tts_text_node.py):
- Extract actual waveform tensor from audio dict before creating voice_mapping
- Applied to all 6 places where audio_tensor is used:
- Narrator voice mapping (line 1151)
- Character ICL fallback (line 1183)
- Character x_vector fallback (line 1217)
- Character no-text fallback (line 1220)
- Character no-audio fallback (line 1237)
- Pattern: Check if audio_tensor is dict, extract waveform/sample_rate if so
**Qwen3-TTS Adapter** (engines/adapters/qwen3_tts_adapter.py):
- Extract inner audio dict before passing to hash function
- Changed from passing full voice_ref to passing voice_ref['audio']
**Audio Hash Utility** (utils/audio/audio_hash.py):
- Added nested structure handling with fallback
- Detects Character Voices format {"audio": {...}} vs direct format
- Enhanced debug logging to diagnose structure issues
## Testing
- Voice Designer → TTS Text: Works without hash error
- Character Voices → TTS Text: Works without hash error
- Audio hashing generates stable keys for caching
- Both VoiceDesign and traditional voices function correctly
Only print individual patch application messages when patches are actually
applied (when verbose=True in each specific patch method). Removes noisy
summary messages like 'Applied 4 transformers compatibility patches' that
provide no actionable information.
The transformers 4.54+ compatibility issue is now resolved by setting
tie_word_embeddings=false in the model config.json. The monkey-patch
workaround is no longer needed.
Fixes critical bug where transformers 4.54+ incorrectly ties lm_head weights
to embed_tokens, causing Step Audio EditX to generate text tokens instead of
audio tokens (silent/gibberish output).
Root cause:
- Transformers 4.54+ ties lm_head to embed_tokens even when checkpoint has different values
- Step-Audio-EditX has lm_head (norm=227) and embed_tokens (norm=255) as separate weights
- Tying overwrites correct lm_head, breaking audio generation
Changes:
- model_loader.py: Add workaround to restore correct lm_head weights after loading
- Detects incorrect weight tying by comparing data pointers
- Loads correct lm_head.weight from safetensors
- Works with transformers 4.54-4.57+
- Clean up debug code and console spam:
- Remove torch_complex warnings (funasr_detach files)
- Remove sox import and unused audio functions
- Silence FunASR registration tables
- Filter torchaudio deprecation warnings
Upstream fix:
- Submitted PR to transformers: https://github.com/huggingface/transformers/pull/42612
- Workaround will remain for backward compatibility with unfixed versions
Tested with transformers 4.57.3 - generates audio tokens correctly.
- Clarify that global patch solves TWO issues: TorchCodec DLL + int16 normalization
- Explain timing criticality: patch must apply before torchaudio import
- Remove redundant pytorch_patches call from apply_all_compatibility_patches()
- Update save_audio_safe docstring to explain defense-in-depth approach
- Add detailed docstring to pytorch_patches explaining both issues and fixes
Recreate pytorch_patches.py with proper global monkey-patching of torchaudio.save/load
to use scipy.io.wavfile instead of TorchCodec. This fixes 'Could not load libtorchcodec'
errors on Windows with PyTorch 2.9.0+cu128 without needing fixes in every file.
Changes:
- Global monkey-patch applied at startup via comfyui_compatibility.py
- Works for ALL code that uses torchaudio.save/load (recorder, voice changer, etc)
- No user setup required, no FFmpeg workarounds needed
- Pure Python scipy solution, no native dependencies
This is the proper fix for TorchCodec Windows incompatibility with PyTorch 2.9.
The pytorch_patches.py file was created to globally monkey-patch torchaudio.save/load
but was never actually applied anywhere. The real fix was normalizing int16 to float
in the Character Voices node after PyTorch 2.9 changed torchaudio.load() behavior.
Since the fix is now working and pytorch_patches.py is unused dead code, remove it.
- Create pytorch_patches.py module for PyTorch/TorchAudio compatibility
- Patch torchaudio.save() and load() to use soundfile for WAV files
- Fixes 'Could not load libtorchcodec' errors on Windows with PyTorch 2.9+
- Only applies patch on PyTorch 2.9+, safe fallback for other versions
- Apply patch in IndexTTS engine before torchaudio operations
Fix transformers compatibility handling
Technical changes:
- Disable legacy DynamicCache patches that masked version conflicts
- Add startup version check for transformers >=4.51.3
- Provide clear upgrade instructions for users with old transformers
- Remove automatic compatibility patches from VibeVoice engine
Centralize numba compatibility system with smart testing
Technical implementation:
- Replace 15+ duplicate JIT workaround blocks with unified system
- Add utils/compatibility/numba_compat.py with startup testing
- Implement fallback for environments without compatibility module
- Test librosa.stft() at startup and apply workarounds only when needed
- Eliminate contradictory startup messages between init and nodes
- Maintain backward compatibility with legacy Python 3.13 fixes
Fix VibeVoice model reloading and transformers compatibility
Technical changes:
- Fix unified model interface cache key missing additional_params
- Add transformers>=4.51.3 requirement for VibeVoice compatibility
- Remove excessive debug prints from VibeVoice engine
- Fix RVC numba JIT disable logic for correct Python version detection
- Fix attention_mode and quantize_llm_4bit not triggering model reloads
- Created utils/compatibility/transformers_patches.py with all monkey patches
- Moved FlashAttentionKwargs, BaseStreamer, DynamicCache, and generation method patches
- Fixed VibeVoice GenerationMixin._prepare_generation_config signature compatibility
- Updated VibeVoice downloader and engine to use centralized patches
- Updated PROJECT_INDEX.md to document compatibility system
- Eliminates duplicate patching logic and improves maintainability