Files
diodiogod-TTS-Audio-Suite/utils/system/subprocess.py
diodiogod 46fda45944 Fix: Remove torchcodec dependency to eliminate FFmpeg system requirement
Removed torchcodec from requirements.txt and install.py to eliminate the FFmpeg
system dependency that was causing Windows installation failures.

Implementation:
- Removed torchcodec>=0.2.0 from requirements.txt
- Removed torchcodec>=0.2.0 from install.py core_packages list
- Removed torchaudio 2.9+ migration warnings (no longer applicable)
- Added AudioProcessingUtils.safe_load_audio() utility for robust audio loading
- Updated all audio loading calls to use fallback-aware utility function

Audio Loading Changes:
- character_voices_node.py: Uses safe_load_audio() with fallback support
- tts_text_node.py: Uses safe_load_audio() for narrator and character voices (2x)
- tts_srt_node.py: Uses safe_load_audio() for narrator voice
- higgs_audio_tts_processor.py: Uses safe_load_audio() (2x)
- higgs_audio_srt_processor.py: Uses safe_load_audio() (2x)
- index_tts_processor.py: Uses safe_load_audio() (2x)
- f5tts_streaming_adapter.py: Uses safe_load_audio()
- higgs_audio_adapter.py: Uses safe_load_audio()
- subprocess.py: Uses safe_load_audio()

Compatibility:
- torchaudio.load() works fine with fallback backends (soundfile, scipy)
- No quality loss - only negligible audio loading speed difference (~milliseconds)
- All existing audio formats supported
- Better error handling with graceful fallbacks
2025-11-05 22:26:10 -03:00

115 lines
4.1 KiB
Python

#!/usr/bin/env python3
"""
ChatterBox TTS Subprocess Wrapper
This script runs ChatterBox TTS generation in an isolated subprocess to prevent
CUDA crashes from affecting the main ComfyUI process.
Usage:
python chatterbox_subprocess.py --text "Hello world" --reference_audio "path/to/ref.wav" --output "output.wav"
"""
import sys
import os
import argparse
import json
import traceback
import tempfile
import torch
import numpy as np
from pathlib import Path
# Add the project root to Python path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
def main():
parser = argparse.ArgumentParser(description='ChatterBox TTS Subprocess')
parser.add_argument('--text', required=True, help='Text to synthesize')
parser.add_argument('--reference_audio', required=True, help='Path to reference audio')
parser.add_argument('--output', required=True, help='Output audio file path')
parser.add_argument('--device', default='auto', help='Device to use (auto/cuda/cpu)')
parser.add_argument('--exaggeration', type=float, default=0.5, help='Exaggeration factor')
parser.add_argument('--temperature', type=float, default=0.8, help='Temperature')
parser.add_argument('--cfg_weight', type=float, default=0.5, help='CFG weight')
parser.add_argument('--seed', type=int, default=0, help='Random seed')
args = parser.parse_args()
try:
# Import ChatterBox TTS modules
from engines.chatterbox.tts import ChatterboxTTS
import torchaudio
print(f"🔄 Subprocess: Loading ChatterBox TTS on {args.device}...")
# Initialize ChatterBox TTS
if args.device == 'auto':
device = 'cuda' if torch.cuda.is_available() else 'cpu'
else:
device = args.device
chatterbox = ChatterboxTTS.from_pretrained(device=device)
print(f"🔄 Subprocess: Loading reference audio from {args.reference_audio}...")
# Load reference audio with fallback support
from utils.audio.processing import AudioProcessingUtils
ref_audio, sample_rate = AudioProcessingUtils.safe_load_audio(args.reference_audio)
# Ensure mono audio
if ref_audio.shape[0] > 1:
ref_audio = ref_audio.mean(dim=0, keepdim=True)
# Resample if necessary
if sample_rate != chatterbox.sr:
resampler = torchaudio.transforms.Resample(sample_rate, chatterbox.sr)
ref_audio = resampler(ref_audio)
print(f"🔄 Subprocess: Generating speech for text: '{args.text[:50]}...'")
# Set seed for reproducibility
if args.seed != 0:
torch.manual_seed(args.seed)
if torch.cuda.is_available():
torch.cuda.manual_seed(args.seed)
# Generate audio
generated_audio = chatterbox.generate(
text=args.text,
reference_audio=ref_audio,
exaggeration=args.exaggeration,
temperature=args.temperature,
cfg_weight=args.cfg_weight
)
print(f"🔄 Subprocess: Saving audio to {args.output}...")
# Save output audio
torchaudio.save(args.output, generated_audio.cpu(), chatterbox.sr)
# Return success info
duration = generated_audio.size(-1) / chatterbox.sr
result = {
'success': True,
'output_path': args.output,
'duration': duration,
'sample_rate': chatterbox.sr,
'audio_shape': list(generated_audio.shape)
}
print(f"✅ Subprocess: Generation completed successfully ({duration:.2f}s)")
print(json.dumps(result))
except Exception as e:
error_result = {
'success': False,
'error': str(e),
'traceback': traceback.format_exc()
}
print(f"❌ Subprocess: Generation failed: {e}")
print(json.dumps(error_result))
sys.exit(1)
if __name__ == "__main__":
main()