chattts_model.py
利用chattts来生成语音。具体看我上一篇文章。
import ChatTTS
import torch
import torchaudio
from typing import Union, List
def generate_speech(
text: Union[str, List[str]],
embedding_path: str = 'seed_11_restored_emb.pt',
output_path: str = 'output.wav',
temperature: float = 0.03
) -> List[str]:
"""
将文本转换为语音并保存为音频文件
参数:
text: 要转换的文本,可以是字符串或字符串列表
embedding_path: 音色嵌入文件的路径
output_path: 输出音频文件的路径(如果是多个文本,会自动添加序号)
temperature: 生成时的温度参数
返回:
生成的音频文件路径列表
"""
# 初始化模型
chat = ChatTTS.Chat()
chat.load_models()
# 加载音色嵌入
spk_emb = torch.load(embedding_path, map_location=torch.device('cpu'))
# 确保文本是列表格式
texts = [text] if isinstance(text, str) else text
# 设置生成参数
params_infer_code = {
'spk_emb': spk_emb,
'temperature': temperature,
}
# 生成语音
wavs = chat.infer(texts, params_infer_code=params_infer_code)
# 保存音频文件
output_files = []
for i, wav in enumerate(wavs):
# 如果是多个文本,给文件名添加序号
if len(wavs) > 1:
file_name, file_ext = output_path.rsplit('.', 1)
current_output = f"{file_name}_{i+1}.{file_ext}"
else:
current_output = output_path
torchaudio.save(current_output, torch.from_numpy(wav), 24000)
output_files.append(current_output)
return output_files
# 使用示例
if __name__ == "__main__":
# 单个文本示例
text = "这是一个带有特定音色的语音合成示例。"
files = generate_speech(text)
print(f"生成的文件: {files}") # 输出: ['output.wav']
# 多个文本示例
texts = [
"第一句话。",
"第二句话。"
]
files = generate_speech(texts, output_path='multiple_outputs.wav')
print(f"生成的文件: {files}") # 输出: ['multiple_outputs_1.wav', 'multiple_outputs_2.wav']
presentation.py
讲一个数组做成一个纯文字的讲述视频。用的是manim这个库。
import os
from manim import *
import subprocess
class TextPresentation(Scene):
"""幻灯片演示场景类
用于创建带有文字和语音的幻灯片演示视频。
继承自manim的Scene类。
"""
def __init__(self, slides, *args, **kwargs):
"""初始化演示场景
Args:
slides: 包含幻灯片文本内容的列表
*args: 传递给父类的位置参数
**kwargs: 传递给父类的关键字参数
"""
super().__init__(*args, **kwargs)
self.slides = slides
def construct(self):
"""构建动画场景
遍历所有幻灯片内容,为每张幻灯片创建文字动画和语音播放。
包含淡入淡出动画效果和同步的语音播放。
"""
for i, content in enumerate(self.slides):
# 创建文本对象
text = Text(content, font_size=48)
# 计算对应的语音文件时长
audio_file = f"speech_{i}.mp3"
audio_duration = self.get_audio_duration(audio_file)
# 添加文本淡入动画
self.play(FadeIn(text))
# 播放对应的语音文件
self.add_sound(audio_file)
# 等待语音播放完毕
self.wait(audio_duration)
# 添加文本淡出动画
self.play(FadeOut(text))
def get_audio_duration(self, audio_file):
"""获取音频文件的时长
使用ffprobe工具读取音频文件时长。
Args:
audio_file: 音频文件路径
Returns:
float: 音频时长(秒)
如果读取失败则返回默认值3.0秒
"""
try:
# 使用 ffprobe 获取音频时长
cmd = [
'ffprobe',
'-v', 'error',
'-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1',
audio_file
]
output = subprocess.check_output(cmd).decode().strip()
duration = float(output)
print(f"音频 {audio_file} 的时长为: {duration} 秒")
return duration
except Exception as e:
print(f"警告:无法读取音频文件 {audio_file} 的时长: {e}")
# 返回一个默认时长
return 3.0
def generate_voice(slides):
"""使用ChatTTS生成语音文件
为每个幻灯片文本生成对应的语音文件。
如果语音文件已存在则跳过生成。
Args:
slides: 包含幻灯片文本内容的列表
"""
from chattts_model import generate_speech
for i, text in enumerate(slides):
output_file = f"speech_{i}.mp3"
# 检查文件是否已存在
if os.path.exists(output_file) and os.path.getsize(output_file) > 0:
print(f"音频文件 {output_file} 已存在,跳过生成")
continue
try:
# 使用 chattts_demo 的 generate_speech 函数
generate_speech(
text=text,
embedding_path='seed_11_restored_emb.pt', # 使用默认的音色嵌入文件
output_path=output_file,
temperature=0.03
)
print(f"已生成语音文件:{output_file}")
except Exception as e:
print(f"生成语音时出错:{e}")
def main():
"""主函数
完整的演示视频生成流程:
1. 定义幻灯片内容
2. 生成语音文件
3. 配置视频参数
4. 渲染动画场景
"""
# 定义幻灯片内容
slides = [
"欢迎来到本次演讲。",
"以下是我们的议程。",
"谢谢您的聆听。"
]
# 检查并生成语音文件
print("正在生成语音文件...")
generate_voice(slides)
print("语音文件生成完毕。")
# 创建并渲染Manim动画
print("正在渲染视频,请稍候...")
# 修改配置,确保包含音频
config.media_width = "1920px" # 设置视频宽度
config.frame_rate = 30 # 设置帧率
config.write_to_movie = True # 确保写入视频文件
config.save_sections = True # 保存所有部分
config.output_file = "presentation_with_audio" # 指定输出文件名
config.write_sound = True # 确保写入声音
# 实例化场景对象
scene = TextPresentation(slides)
# 渲染场景
scene.render()
print("视频渲染完毕。")
# 清理生成的音频文件(可选)
# for i in range(len(slides)):
# os.remove(f"speech_{i}.mp3")
if __name__ == "__main__":
main()
-
文件结构
- chattts_model.py:负责语音生成
- presentation.py:负责视频制作
- seed_11_restored_emb.pt:音色文件
-
chattts_model.py 功能
- 输入:文本(单条或多条)
- 处理步骤:
- 初始化 ChatTTS 模型
- 加载音色文件
- 生成语音
- 保存为音频文件
- 输出:音频文件列表
-
presentation.py 功能
-
TextPresentation 类:
- 创建文字动画
- 添加淡入淡出效果
- 同步语音播放
- 控制动画时长
-
generate_voice 函数:
- 检查语音文件是否存在
- 调用 chattts_model.py 生成语音
- 保存为 mp3 格式
-
get_audio_duration 函数:
- 使用 ffprobe 获取音频时长
- 失败时返回默认值 3.0 秒
-
-
运行流程
-
准备阶段:
- 定义文本内容
- 设置视频参数
-
生成阶段:
- 生成语音文件
- 创建文字动画
- 同步音频
-
输出阶段:
- 渲染最终视频
- 可选清理临时文件
-
-
使用要求
- 环境依赖:
- Manim 库
- ChatTTS
- ffprobe 工具
- 环境依赖: