import ChatTTS
import torch
import numpy as np
import torchaudio
import re
import time
# 记录开始时间
start_time = time.time()
# 设置环境变量以避免内存碎片化
import os
os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'expandable_segments:True'
# 使用 CPU 进行计算
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
chat = ChatTTS.Chat()
chat.load(compile=False) # Set to True for better performance
text = """
小品文的体裁多种多样,有游记、速写、随笔、杂感(或称杂文),寓言、序、尺牍等。这些文体在古人看来,与诗文正统文学相比是不登大雅之堂的,故在古代分类的文体论中,不见有单独的“小品文”一类。中国的文体论,发轫于魏晋,盛于齐梁以后。曹丕的《典论·论文》中把文分为奏议、书论、铭诔;陆机的《文赋》将文体分为九类,即赋、碑、诔,铭、箴、颂、论、奏、说,属于“文”的有六种;晋·挚虞的《文章流别论》中也把文分为九类:诗、颂、赋、七、箴、铭、诔、哀、碑,属于文的有五种。至南北朝,刘勰在《文心雕龙》中提出了著名的文、笔说,“无韵者笔也”,笔指各种散体文,他所列的二十种文体中,属于无韵文的有十种,还出现了“杂文”这一名称(不过它属于韵文),就是还没有“小品文”。梁·昭明太子的《文选》将诗文分为三十八类,属于散文的有二十一种;到了明代吴讷的《文章辨体》和徐师曾的《文体明辨》,入选的文体更广泛,分类更细密,前者共分文体五十九类,后者搜罗文体一百二十七类,还是没有提及“小品文”这一名称。 [2]
"""
# 使用固定音色
guding_spk = torch.load("speaker/seed_2279.pt", map_location=device, weights_only=True)
# 相关参数,见文档说明
params_infer_code = ChatTTS.Chat.InferCodeParams(
spk_emb=guding_spk, # add sampled speaker
temperature=.3, # using custom temperature
top_P=0.7, # top P decode
top_K=20, # top K decode,
)
# 根据效果自行选择
# use oral_(0-9), laugh_(0-2), break_(0-7)
# to generate special token in text to synthesize.
params_refine_text = ChatTTS.Chat.RefineTextParams(
prompt='[oral_0][laugh_0][break_6]',
)
def remove_bracketed_content(text):
"""
移除文本中所有以 [ 开头和 ] 结尾且中间包含字母或数字的内容。
"""
return re.sub(r'\[\w+\]', '', text)
def replace_punctuation_with_uv_break(text):
"""
将文本中的标点符号替换为 [uv_break]。
"""
# 定义常见的标点符号
punctuation_pattern = r'[();;·:“”【】《》、…:—]'
return re.sub(punctuation_pattern, ',', text)
text1=remove_bracketed_content(text)
# print(text1)
text=replace_punctuation_with_uv_break(text1)
# print(text)
def text_to_sentences(text, max_length=180, sub_max_length=90):
# 去除多余的空行和缩进
text = re.sub(r'\s+', ' ', text).strip()
# 使用正则表达式根据标点符号分割句子
sentence_endings = re.compile(r'(?<=[。!?])')
raw_sentences = sentence_endings.split(text)
sentences = []
current_sentence = ""
for sentence in raw_sentences:
sentence = sentence.strip()
if not sentence:
continue
# 如果当前句子加上新句子超过 sub_max_length,则先保存当前句子
if len(current_sentence) + len(sentence) + 1 > sub_max_length:
if current_sentence:
sentences.append(current_sentence)
current_sentence = ""
# 如果新句子本身超过 sub_max_length,则进一步分割
if len(sentence) > sub_max_length:
sub_start = 0
while sub_start < len(sentence):
sub_end = sub_start + sub_max_length
if sub_end < len(sentence):
sub_end = sentence.rfind(' ', sub_start, sub_end)
if sub_end == -1:
sub_end = sub_start + sub_max_length
sub_sentence = sentence[sub_start:sub_end].strip()
if sub_sentence:
sentences.append(sub_sentence)
sub_start = sub_end + 1
else:
# 如果当前句子为空,则直接赋值
if not current_sentence:
current_sentence = sentence
else:
current_sentence += " " + sentence
# 添加最后一个句子
if current_sentence:
sentences.append(current_sentence)
return sentences
# def text_to_sentences(text, max_length=180, sub_max_length=90):
# # 去除多余的空行和缩进
# text = re.sub(r'\s+', ' ', text).strip()
#
# sentences = []
# start = 0
# while start < len(text):
# end = start + max_length
# if end < len(text):
# # 找到最后一个空格的位置,确保不会截断单词
# end = text.rfind(' ', start, end)
# if end == -1:
# end = start + max_length
# sentence = text[start:end].strip()
# if len(sentence) > sub_max_length:
# # 进一步分割长句子
# sub_start = 0
# while sub_start < len(sentence):
# sub_end = sub_start + sub_max_length
# if sub_end < len(sentence):
# sub_end = sentence.rfind(' ', sub_start, sub_end)
# if sub_end == -1:
# sub_end = sub_start + sub_max_length
# sub_sentence = sentence[sub_start:sub_end].strip()
# if sub_sentence:
# sentence = sentence
# sentences.append(sub_sentence)
# sub_start = sub_end + 1
# else:
# if sentence:
# sentence=sentence
# sentences.append(sentence)
# start = end + 1
#
# return sentences
# def text_to_sentences(text):
# # 去除多余的空行和缩进
# text = re.sub(r'\s+', ' ', text).strip()
#
# # 使用中文标点符号分割文本,并去除空字符串
# punctuation_pattern = r'[,。!?;:“”‘’()【】《》、…:—]'
# sentences = [sentence.strip() for sentence in re.split(punctuation_pattern, text) if sentence.strip()]
#
# return sentences
# 将文本分割成列表
texts = text_to_sentences(text)
print(texts)
wavs = []
for text in texts:
wav = chat.infer(text, skip_refine_text=True, params_refine_text=params_refine_text, params_infer_code=params_infer_code)
# 确保音频数据是一维数组
if wav.ndim > 1:
wav = wav.squeeze()
wavs.append(wav)
def merge_wavs(wavs, output_file, sample_rate=24000):
# 将所有wav数据连接成一个numpy数组
merged_wav = np.concatenate(wavs, axis=0)
# 转换为torch张量并添加通道维度
merged_wav_tensor = torch.from_numpy(merged_wav).unsqueeze(0)
# 保存合并后的音频文件
torchaudio.save(output_file, merged_wav_tensor, sample_rate)
# def merge_wavs(wavs, output_file, sample_rate=24000):
# # 检查所有音频数据的形状
# max_length = max(wav.shape[0] for wav in wavs)
# standardized_wavs = []
# for wav in wavs:
# if wav.shape[0] < max_length:
# # 填充较短的音频
# padded_wav = np.pad(wav, (0, max_length - wav.shape[0]), mode='constant')
# standardized_wavs.append(padded_wav)
# else:
# standardized_wavs.append(wav)
#
# # 将所有wav数据连接成一个numpy数组
# merged_wav = np.concatenate(standardized_wavs, axis=0)
#
# # 转换为torch张量并添加通道维度
# merged_wav_tensor = torch.from_numpy(merged_wav).unsqueeze(0)
#
# # 保存合并后的音频文件
# torchaudio.save(output_file, merged_wav_tensor, sample_rate)
try:
merge_wavs(wavs, "荷塘月色_children.wav", 24000)
except Exception as e:
print(f"Error merging wavs: {e}")
finally:
# 释放未使用的缓存
torch.cuda.empty_cache()
# 记录结束时间
end_time = time.time()
# 计算并打印耗时
elapsed_time = end_time - start_time
print(f"Total time taken: {elapsed_time:.2f} seconds")
chatts长文本测试代码。
最新推荐文章于 2025-02-20 14:30:02 发布