Merge pull request #32 from set-soft/better_lang

[Lyrics Language Switch] Better handling of latin languages
This commit is contained in:
MW
2025-05-18 09:03:35 +08:00
committed by GitHub
+55 -13
View File
@@ -10,16 +10,15 @@ if current_dir not in sys.path:
from ace_step.language_segmentation import LangSegment
from ace_step.ace_models.lyrics_utils.lyric_tokenizer import VoiceBpeTokenizer
lyric_tokenizer = VoiceBpeTokenizer()
lang_segment = LangSegment()
SUPPORT_LANGUAGES = {
"en": 259, "de": 260, "fr": 262, "es": 284, "it": 285,
"pt": 286, "pl": 294, "tr": 295, "ru": 267, "cs": 293,
"nl": 297, "ar": 5022, "zh": 5023, "ja": 5412, "hu": 5753,
"ko": 6152, "hi": 6680
}
lyric_tokenizer = VoiceBpeTokenizer()
lang_segment = LangSegment()
lang_segment.langid.set_languages(list(SUPPORT_LANGUAGES.keys()))
lang_segment.setfilters([
'af', 'am', 'an', 'ar', 'as', 'az', 'be', 'bg', 'bn', 'br', 'bs', 'ca', 'cs', 'cy', 'da', 'de', 'dz', 'el',
'en', 'eo', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr', 'ga', 'gl', 'gu', 'he', 'hi', 'hr', 'ht', 'hu', 'hy',
@@ -30,10 +29,13 @@ lang_segment.setfilters([
])
def get_lang(text):
def get_lang(text, default_lang, threshold):
language = "en"
try:
_ = lang_segment.getTexts(text)
words = lang_segment.getTexts(text)
print(words)
if words[0]['score'] < threshold:
return default_lang
langCounts = lang_segment.getCounts()
language = langCounts[0][0]
if len(langCounts) > 1 and language == "en":
@@ -42,7 +44,8 @@ def get_lang(text):
language = "en"
return language
def tokenize_lyrics(lyrics):
def tokenize_lyrics(lyrics, default_lang, threshold):
lines = lyrics.split("\n")
lyric_token_idx = []
for line in lines:
@@ -51,7 +54,7 @@ def tokenize_lyrics(lyrics):
lyric_token_idx += ["\n"]
continue
lang = get_lang(line)
lang = get_lang(line, default_lang, threshold)
if lang not in SUPPORT_LANGUAGES:
lang = "en"
@@ -63,8 +66,7 @@ def tokenize_lyrics(lyrics):
structure_pattern = re.compile(r"\[.*?\]")
try:
if structure_pattern.match(line):
token_idx = lyric_tokenizer.preprocess_text(line, "en")
lyric_token_idx.append(token_idx + "\n")
lyric_token_idx.append(line + "\n")
else:
token_idx = lyric_tokenizer.preprocess_text(line, lang)
lyric_token_idx.append(f"[{lang}]" + token_idx + "\n")
@@ -75,6 +77,34 @@ def tokenize_lyrics(lyrics):
class LyricsLangSwitch:
# Mapping of language codes to display names
LANGUAGE_MAP = {
"en": "English",
"de": "German",
"fr": "French",
"es": "Spanish",
"it": "Italian",
"pt": "Portuguese",
"pl": "Polish",
"tr": "Turkish",
"ru": "Russian",
"cs": "Czech",
"nl": "Dutch",
"ar": "Arabic",
"zh": "Chinese",
"ja": "Japanese",
"hu": "Hungarian",
"ko": "Korean",
"hi": "Hindi"
}
# Create a list of display names for the dropdown
LANGUAGE_DISPLAY_NAMES = sorted(list(LANGUAGE_MAP.values()))
# Create a reverse mapping to easily get the code from the display name
# This is efficient for lookup in the lyricsgen method
REVERSE_LANGUAGE_MAP = {v: k for k, v in LANGUAGE_MAP.items()}
@classmethod
def INPUT_TYPES(cls):
@@ -83,7 +113,14 @@ class LyricsLangSwitch:
"lyrics": ("STRING", {
"multiline": True,
"default": "[verse]\n我走过深夜的街道\n冷风吹乱思念的漂亮外套\n你的微笑像星光很炫耀\n照亮了我孤独的每分每秒\n\n[chorus]\n愿你是风吹过我的脸\n带我飞过最远最遥远的山间\n愿你是风轻触我的梦\n停在心头不再飘散无迹无踪\n\n[verse]\n一起在喧哗避开世俗的骚动\n独自在天台探望月色的朦胧\n你说爱像音乐带点重节奏\n一拍一跳让我忘了心的温度多空洞\n\n[bridge]\n唱起对你的想念不隐藏\n像诗又像画写满藏不了的渴望\n你的影子挥不掉像风的倔强\n追着你飞扬穿越云海一样泛光\n\n[chorus]\n愿你是风吹过我的手\n暖暖的触碰像春日细雨温柔\n愿你是风盘绕我的身\n深情万万重不会有一天走远走\n\n[verse]\n深夜的钢琴弹起动人的旋律\n低音鼓砸进心底的每一次呼吸\n要是能将爱化作歌声传递\n你是否会听见我心里的真心实意"}),
},
"language": (cls.LANGUAGE_DISPLAY_NAMES, {"default": cls.LANGUAGE_MAP["en"]}),
"threshold": ("FLOAT", {
"default": 0.8,
"min": 0.0, # Minimum value
"max": 1.0, # Maximum value
"step": 0.01, # Step for the slider/input
"display": "number"}), # or "slider"
},
}
CATEGORY = "🎤MW/MW-ACE-Step"
@@ -91,5 +128,10 @@ class LyricsLangSwitch:
RETURN_NAMES = ("lyrics",)
FUNCTION = "lyricsgen"
def lyricsgen(self, lyrics: str):
return (tokenize_lyrics(lyrics.strip()),)
def lyricsgen(self, lyrics: str, language: str, threshold: float):
# Convert the selected display name back to the language code
language_code = self.REVERSE_LANGUAGE_MAP.get(language)
if language_code is None:
# Fallback or error handling if the display name isn't found
language_code = "en" # Default to 'en' if something goes wrong
return (tokenize_lyrics(lyrics.strip(), language_code, threshold),)