Files
diodiogod-TTS-Audio-Suite/utils/models/language_mapper.py
T
diodiogod 9c0dfc3f94 Add VibeVoice SRT support with unified architecture
Implemented complete VibeVoice SRT processor with dual mode support:

Features:
• Native Multi-Speaker Mode: One segment per subtitle using VibeVoice's Speaker 1:, Speaker 2: format
• Custom Character Switching Mode: Multiple segments per subtitle (one per character)
• Full SRT timing support: stretch_to_fit, pad_with_silence, smart_natural, concatenate
• Modular architecture using existing utils (no code duplication)
• Character switching with voice discovery integration
• Pause tag support in both modes
• Smart language grouping and model switching

Technical Implementation:
• Added VibeVoiceSRTProcessor with complete SRT workflow
• Updated unified SRT node to support vibevoice engine
• Added VibeVoice to language_mapper utility
• Proper ComfyUI audio format handling
• Fixed timing adjustment format for detailed reports

Integration:
• Uses existing timing utils, audio assembly, and reporting modules
• Compatible with Character Voices node
• Maintains same interface as ChatterBox/F5-TTS SRT nodes
2025-08-29 22:35:01 -03:00

178 lines
7.3 KiB
Python

"""
Language Model Mapper - Maps language codes to engine-specific models
Provides centralized language-to-model mapping for F5-TTS and ChatterBox engines
"""
from typing import Dict, List, Optional
class LanguageModelMapper:
"""Maps language codes to engine-specific model names."""
def __init__(self, engine_type: str):
"""
Initialize language model mapper.
Args:
engine_type: "f5tts" or "chatterbox"
"""
self.engine_type = engine_type
self.mappings = self._load_mappings()
def get_model_for_language(self, lang_code: str, default_model: str) -> str:
"""
Map language code to engine-specific model name.
Args:
lang_code: Language code (e.g., 'en', 'de', 'fr') or local model (e.g., 'local:German')
default_model: Default model to use for base language
Returns:
Model name for the specified language
"""
# Handle local models - normalize to base model name
if lang_code.startswith('local:'):
return lang_code[6:] # Remove "local:" prefix - they use same model as base language
engine_mappings = self.mappings.get(self.engine_type, {})
# Check if we should use the default model for this language
# Only use default model if it's actually for the requested language
if lang_code == 'en':
# For English, prefer the default model if it's an English model
if self.engine_type == 'f5tts':
# Check if default model is already an English F5-TTS model
english_models = ['F5TTS_Base', 'F5TTS_v1_Base', 'E2TTS_Base']
if default_model in english_models:
return default_model # Use engine's configured model
else:
return 'F5TTS_v1_Base' # Use v1 for better quality as fallback
elif self.engine_type == 'chatterbox':
return 'English'
elif self.engine_type == 'vibevoice':
# VibeVoice uses same model for both EN/ZH, so use configured model
vibevoice_models = ['vibevoice-1.5B', 'vibevoice-7B']
if default_model in vibevoice_models:
return default_model # Use engine's configured model
else:
return 'vibevoice-1.5B' # Default fallback
# Check if language is supported
if lang_code in engine_mappings:
return engine_mappings[lang_code]
else:
# Language not supported - show warning and fallback to default
print(f"⚠️ {self.engine_type.title()}: Language '{lang_code}' not supported, falling back to English model")
return default_model
def get_supported_languages(self) -> List[str]:
"""Get list of supported language codes for current engine."""
engine_mappings = self.mappings.get(self.engine_type, {})
return list(engine_mappings.keys())
def is_language_supported(self, lang_code: str) -> bool:
"""Check if a language is supported by current engine."""
return lang_code in self.get_supported_languages()
@staticmethod
def _load_mappings() -> Dict[str, Dict[str, str]]:
"""Load language mappings from config."""
return {
"f5tts": {
"en": "F5TTS_Base", # This will be overridden by default_model
"de": "F5-DE", # German
"es": "F5-ES", # Spanish
"fr": "F5-FR", # French
"it": "F5-IT", # Italian
"jp": "F5-JP", # Japanese
"th": "F5-TH", # Thai
"pt": "F5-PT-BR", # Portuguese (Brazil)
"pt-br": "F5-PT-BR", # Portuguese (Brazil) - alternative format
"hi": "F5-Hindi-Small", # Hindi - uses Small model from IIT Madras
# Note: Other Indian languages (as, bn, gu, kn, ml, mr, or, pa, ta, te) fall back to base F5TTS models
# IndicF5 was removed due to architecture incompatibility
},
"chatterbox": {
"en": "English", # This will be overridden by default_model
"de": "German", # German
"no": "Norwegian", # Norwegian
"nb": "Norwegian", # Norwegian Bokmål
"nn": "Norwegian", # Norwegian Nynorsk
},
"vibevoice": {
"en": "vibevoice-1.5B", # This will be overridden by default_model
"zh": "vibevoice-1.5B", # Chinese - same model supports both EN/ZH
"zh-cn": "vibevoice-1.5B", # Simplified Chinese
"chinese": "vibevoice-1.5B", # Alternative format
# VibeVoice models support both English and Chinese with the same model
}
}
def get_all_mappings(self) -> Dict[str, Dict[str, str]]:
"""Get all language mappings for all engines."""
return self.mappings
def add_language_mapping(self, lang_code: str, model_name: str):
"""
Add or update a language mapping for current engine.
Args:
lang_code: Language code
model_name: Model name for this language
"""
if self.engine_type not in self.mappings:
self.mappings[self.engine_type] = {}
self.mappings[self.engine_type][lang_code] = model_name
def remove_language_mapping(self, lang_code: str):
"""
Remove a language mapping for current engine.
Args:
lang_code: Language code to remove
"""
if self.engine_type in self.mappings and lang_code in self.mappings[self.engine_type]:
del self.mappings[self.engine_type][lang_code]
# Global instances for easy access
f5tts_language_mapper = LanguageModelMapper("f5tts")
chatterbox_language_mapper = LanguageModelMapper("chatterbox")
vibevoice_language_mapper = LanguageModelMapper("vibevoice")
def get_language_mapper(engine_type: str) -> LanguageModelMapper:
"""
Get language mapper instance for specified engine.
Args:
engine_type: "f5tts", "chatterbox", or "vibevoice"
Returns:
LanguageModelMapper instance
"""
if engine_type == "f5tts":
return f5tts_language_mapper
elif engine_type == "chatterbox":
return chatterbox_language_mapper
elif engine_type == "vibevoice":
return vibevoice_language_mapper
else:
raise ValueError(f"Unknown engine type: {engine_type}")
def get_model_for_language(engine_type: str, lang_code: str, default_model: str) -> str:
"""
Convenience function to get model for language.
Args:
engine_type: "f5tts", "chatterbox", or "vibevoice"
lang_code: Language code
default_model: Default model for base language
Returns:
Model name for the specified language
"""
mapper = get_language_mapper(engine_type)
return mapper.get_model_for_language(lang_code, default_model)