教你将一个数组瞬间生成一个纯文字的放映视频。使用chattts和manim。

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()
  1. 文件结构

    1. chattts_model.py:负责语音生成
    2. presentation.py:负责视频制作
    3. seed_11_restored_emb.pt:音色文件
  2. chattts_model.py 功能

    1. 输入:文本(单条或多条)
    2. 处理步骤:
      1. 初始化 ChatTTS 模型
      2. 加载音色文件
      3. 生成语音
      4. 保存为音频文件
    3. 输出:音频文件列表
  3. presentation.py 功能

    1. TextPresentation 类:

      1. 创建文字动画
      2. 添加淡入淡出效果
      3. 同步语音播放
      4. 控制动画时长
    2. generate_voice 函数:

      1. 检查语音文件是否存在
      2. 调用 chattts_model.py 生成语音
      3. 保存为 mp3 格式
    3. get_audio_duration 函数:

      1. 使用 ffprobe 获取音频时长
      2. 失败时返回默认值 3.0 秒
  4. 运行流程

    1. 准备阶段:

      1. 定义文本内容
      2. 设置视频参数
    2. 生成阶段:

      1. 生成语音文件
      2. 创建文字动画
      3. 同步音频
    3. 输出阶段:

      1. 渲染最终视频
      2. 可选清理临时文件
  5. 使用要求

    1. 环境依赖:
      1. Manim 库
      2. ChatTTS
      3. ffprobe 工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值