add banbanmini backend

This commit is contained in:
HycJack
2026-03-24 15:04:36 +08:00
parent 0d0f995dc2
commit 7510ca6df1
197 changed files with 13008 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
import re
SENTENCE_ENDINGS = set("。!?!?;:.。\n")
PUNCTUATION_MARKS = set('。!?!?.,;:~…—_\'"""》《)》《<>()[]{}【】\'、~~¡¿äöüßáéíóúüñç\n')
APOSTROPHE_SUFFIXES = {'s', 't', 've', 'll', 're', 'd', 'm'}
LANGUAGE_CONTRACTIONS = {
'fr': ["l'", "d'", "s'", "qu'", "c'", "j'", "n'", "m'", "t'", "jusqu'"],
'de': ["geht's", "gibt's"],
'es': ["el-", "del", "al"],
'ms': ["-lah", "-kah", "-nya"]
}
def is_numbered_list_item(text):
pattern = r"^\s*\d+\.\s"
return bool(re.search(pattern, text))
def split_into_sentences(text):
return _custom_split_sentences(text)
def _custom_split_sentences(text):
text = re.sub(r"([。!?!?;])", r"\1\n", text)
sentences = []
current_sentence = ""
i = 0
while i < len(text):
current_sentence += text[i]
if text[i] in SENTENCE_ENDINGS and not is_special_context(text, i):
if current_sentence.strip():
sentences.append(current_sentence)
current_sentence = ""
i += 1
if current_sentence.strip():
sentences.append(current_sentence)
merged_sentences = []
temp = ""
for s in sentences:
s_stripped = s.strip()
if len(s_stripped) < 5 and not any(p in s for p in "。!?!?"):
temp += s
else:
if temp:
merged_sentences.append(temp + s)
temp = ""
else:
merged_sentences.append(s)
if temp:
merged_sentences.append(temp)
final_sentences = []
for idx, sentence in enumerate(merged_sentences):
sentence_start = sentence.strip()
if idx > 0:
prev_sentence_end = merged_sentences[idx-1].strip()
if (sentence_start.startswith("s ") and prev_sentence_end.endswith("'")) or \
any(sentence_start.startswith(suffix + " ") for suffix in APOSTROPHE_SUFFIXES) and prev_sentence_end.endswith("'"):
final_sentences[-1] += sentence
continue
if any(sentence_start.startswith(contraction) for contraction in LANGUAGE_CONTRACTIONS['fr']):
final_sentences[-1] += sentence
continue
if (any(prev_sentence_end.endswith(contraction) for contraction in LANGUAGE_CONTRACTIONS['de']) or
any(sentence_start.startswith(contraction) for contraction in LANGUAGE_CONTRACTIONS['es']) or
any(prev_sentence_end.endswith(contraction) for contraction in LANGUAGE_CONTRACTIONS['ms'])):
final_sentences[-1] += sentence
continue
if sentence_start.startswith("¿") or sentence_start.startswith("¡"):
final_sentences.append(sentence)
continue
final_sentences.append(sentence)
return final_sentences
def is_special_context(text, pos):
"""判断是否是特殊上下文,不应该在此处断句"""
if text[pos] == "." and pos > 0 and pos < len(text) - 1:
if text[pos - 1].isdigit() and text[pos + 1].isdigit():
return True
if text[pos] == "'" and pos > 0 and pos < len(text) - 1:
if text[pos - 1].isalpha(): # 前面是字母
for suffix in APOSTROPHE_SUFFIXES:
if pos + len(suffix) <= len(text) and text[pos+1:pos+1+len(suffix)] == suffix:
if pos + len(suffix) + 1 >= len(text) or not text[pos+1+len(suffix)].isalpha():
return True
if text[pos] == "." and pos > 0 and pos < len(text) - 2:
if text[pos - 1].isupper() and text[pos + 1].isupper():
return True
if text[pos] == "." and pos > 0 and pos < len(text) - 1:
if not text[pos - 1].isspace() and not text[pos + 1].isspace():
left_context = text[max(0, pos-15):pos]
if "www." in left_context or "http" in left_context or "@" in left_context:
return True
if text[pos] == "." and pos > 0 and pos < len(text) - 1:
if pos + 2 < len(text) and text[pos:pos+3] == "...":
return True
if text[pos] == "'" and pos > 0 and pos < len(text) - 1:
if pos > 1 and text[pos-2:pos+1] in ["l'", "d'", "c'", "j'", "n'", "m'", "t'"]:
return True
if text[pos] == "." and pos > 0:
if pos >= 3 and text[pos-3:pos] in ["bzw", "usw", "etc"]:
return True
if text[pos] in "¿¡" and pos < len(text) - 1:
return True
if text[pos] == "-" and pos > 0 and pos < len(text) - 2:
if text[pos+1:pos+4] in ["lah", "kah", "nya"]:
return True
return False
def should_skip_tts(text_chunk):
"""判断一段文本是否应该跳过TTS处理"""
if not text_chunk.strip():
return True
if is_numbered_list_item(text_chunk) and len(text_chunk.strip()) <= 5:
return True
if all(c in PUNCTUATION_MARKS for c in text_chunk.strip()):
return True
if len(text_chunk.strip()) <= 2 and not any(c.isalnum() for c in text_chunk):
return True
return False