【大模型】AI视频课程制作工具开发

1. 需求信息

1.1 需求背景

讲师们在制作视频的过程中,发现录制课程比较麻烦,要保证环境安静,保证录制过程不出错,很容易反复重复录制,为了解决重复录制的工作量,想通过 ai 课程制作工具,来解决这些问题。

2. 业务分析

2.1 视频生成过程

  1. 视频素材来源: 首先由产品研发团队的产品、架构师协助提供基础资料,根据产品材料来输出ppt文档;
  2. 素材上传:使用的授课课件材料,如:PPT 或 PDF(也有doc课件大纲、课程详细内容,现在我们基本上用不上),上传到AI视频制作工具平台;
  3. 素材文本提取:a. 提取素材文本内容(ppt内容+备注);b. 将素材截图成图片;
  4. 演讲稿制作:将第3步提取的文字,交由混元来生成讲课稿,这里可以人工校验句子合理性;
  5. 演讲稿合成语音:将第4步生成的讲课稿合成音频文件;
  6. 合成视频:将音频、图片合成视频。

其中,2~6可以合成一步,就是在有讲课稿的情况下,直接提取备注合成视频。

2.2 视频课程权限

  1. 数据隔离和安全:课程以空间的概念相互隔离, 用户使用OA登录系统后,默认不可见其他同事创建的空间,只能看到自己创建的空间。
  2. 数据共享协作:空间创建者默认拥有空间管理权限,可以邀请其他同事协作;
  3. 超级管理员:超级管理员课件所以课件,超级管理员不可配置,只能研发修改数据库角色。

2.4 发音修正

部分专业英文缩写发音不准的问题,可以通过SMAL标记语言修正发音,因此提供一个发音修正管理菜单,用户可以自定义发音部分单词。

2.5 用户登录限制

  1. 系统接入OA登录,只能在内网访问;
  2. 给用户添加权限,必须在用户登录过系统之后,才能添加(必须用户登录之后,系统才会记录用户信息)。

3. 技术设计

3.1 视频制作流程

目前我们的技术方案是腾讯云语音合成(TTS)+视频合成(云点播)+混元大模型来搭建的。支持2种方式来生成视频:

  1. 无讲课稿的情况下,通过解析读取ppt文档的内容和备注, 调用混元大模型来生成演讲稿, 演讲稿生成语音, 再截取PPT的图片,来合成视频;
  2. 有讲课稿的情况下, 支持一件生成讲课视频。

整体流程入下图所示:

在这里插入图片描述

3.2 发音纠正

由于课程内容主要是腾讯云的产品培训,因此有很多腾讯云相关的专有英文名词和缩写,腾讯云TTS对这些词的合成不够理想,不过提供了SSML 标记语言,用来自定义纠正发音,如上图发音纠正部分。

3.3 相关技术工具

  1. 腾讯云对象存储cos,制作课程过程中的各种素材,包括:文件、图片、音频、视频等都是存储在cos里面
  2. 数据万象: PPT转PDF使用的是cos 自带的数据万象能力,可以把ppt转换为pdf格式文件
  3. 开源工具pptx:可以读取ppt的演讲稿的文本和备注;
  4. 开源工具PyPDF2:可以把pdf文件截取成图;
  5. 混元大模型:提供AIGC能力,写入prompt讲提取的课件文本生成讲课稿;
  6. 语音合成(TTS):使用腾讯云TTS将文本生成生动的语音;
  7. 视频合成:腾讯云点播将音频和图片按时间线生成视频;
  8. 后端web框架:fastapi,一个python的http服务框架;
  9. 前端框架:内部开源的TDesign。

4 问题

4.1 语音合成(TTS)

目前业务方使用反馈最多的是腾讯云TTS的语言合成效果问题,例如:

  1. 专有名词发音不正确;
  2. 同一个语音类型发音过程中切换;
  3. 中、英切换过程中出现不同发音。

针对上述问题已经在尝试2个不同的解决方案:

  1. 推动腾讯云TTS优化:已经拉通TTS产品团队在支持,并逐步在收集发音的base case;
  2. 调研开源TTS语音合成大模型,目前已知的ChatTTS 和阿里开源的CosyVoice 都有非常流畅的效果;
  3. 第三方云平台的TTS 实现,目前国内讯飞的合成效果也不错。

4.2 讲课稿生成

讲课稿的生成过程比较耗时,一个课程小节经常长达100+页ppt,每一页都需要AIGC生成后,还需要人工精调。

针对这个问题可以考虑:

  1. 增强知识库,随着课程制作素材的累积,我们将形成一个优质的知识库,可以提供大模型非常好的知识增强;
  2. 个性化微调大模型:随着数据的积累,可以使用混元一站式训练平台,对针对性微调个性化模型专门用来优化演讲稿生成。

附件

主要python工具包

  • fastapi==0.111.0 // fastapi web框架
  • python-pptx==0.6.23 // pptx 内容读取
  • pdf2image==1.17.0 // pdf转图片
  • tencentcloud-sdk-python==3.0.1132 // 调用腾讯云api

文本提取

from pptx import Presentation
import PyPDF2
import tempfile,io,requests
from dependencies import FILE_NAME_MAX_LENGTH, new_file_name
from logger_config import logger
from repo import schemas
from typing import List
from fastapi import HTTPException
from starlette.status import HTTP_400_BAD_REQUEST, HTTP_200_OK# 提取ppt中的正文和备注
def extract_info_from_ppt(ppt_url: str) -> List[schemas.PPtTextNode]:# 下载PDF文件logger.info('开始下载ppt文件: ' + ppt_url)response = requests.get(ppt_url)if response.status_code != HTTP_200_OK:logger.error("file download failed : " + ppt_url)raise HTTPException(status_code=HTTP_400_BAD_REQUEST,detail="文件下载失败",)pdf_bytes = response.content# 将字节流转换为文件对象file_obj = io.BytesIO(pdf_bytes)# 加载 PowerPoint 文档presentation = Presentation(file_obj)# 备注内容slide_infos : List[schemas.PPtTextNode] = []# 遍历幻灯片for slide in presentation.slides:# 获取幻灯片上的文本slide_text = ""for shape in slide.shapes:if hasattr(shape, "text"):slide_text += shape.text# 获取幻灯片的备注notes_slide = slide.notes_slide# 获取备注文本notes_text = notes_slide.notes_text_frame.text# 添加到备注列表slide_infos.append(schemas.PPtTextNode(text=slide_text, note=notes_text))return slide_infos
# 提取pdf中的内容
def extract_info_from_pdf(pdf_url: str):# 下载PDF文件logger.info('开始下载PDF文件: ' + pdf_url)response = requests.get(pdf_url)if response.status_code != HTTP_200_OK:raise HTTPException(status_code=HTTP_400_BAD_REQUEST,detail="文件下载失败",)pdf_bytes = response.content# 将字节流转换为文件对象file_obj = io.BytesIO(pdf_bytes)# 加载 PDF 文件pdf_reader = PyPDF2.PdfReader(file_obj)# 获取 PDF 文件的页数num_pages = len(pdf_reader.pages)# 遍历 PDF 文件的每一页slide_infos : List[schemas.PPtTextNode] = []for page_num in range(num_pages):# 获取当前页page = pdf_reader.pages[page_num]# 提取页面内容content = page.extract_text()# 添加到备注列表silde_info = schemas.PPtTextNode(text=content, notes="")slide_infos.append(silde_info)return slide_infos

pdf转图片

import os
from logic.qcloud import cosclient
import tempfile
from logger_config import logger
import requests,re
from pdf2image import convert_from_bytes
from typing import List
from repo import schemas
import tracemalloc
import configfrom dependencies import FILE_NAME_MAX_LENGTH, new_file_name# 定义一个函数来验证文件名是否安全
def is_safe_filename(filename):# 使用正则表达式来匹配合法的文件名return bool(re.match(r'^[\w\-.]+$', filename))def pdf_url_to_images(pdf_url: str, space_id: int)->List[schemas.PPtToImage]:# 下载PDF文件logger.info('开始下载PDF文件: ' + pdf_url)response = requests.get(pdf_url)pdf_bytes = response.content# 将PPT文件的每一页保存为图像output_folder = tempfile.mkdtemp()# 将PDF文件转换为图像tracemalloc.start()# 获取内存分配情况的快照if config.get_settings().is_tracemalloc == True:snapshot1 = tracemalloc.take_snapshot()images = convert_from_bytes(pdf_bytes)if config.get_settings().is_tracemalloc == True:snapshot2 = tracemalloc.take_snapshot()# 比较两个快照,找出内存分配差异top_stats = snapshot2.compare_to(snapshot1, "lineno")# 打印内存分配差异的统计信息for stat in top_stats[:10]:logger.info("读取文件后,内存分配差异: %s" % stat)total_size = sum(stat.size for stat in snapshot2.statistics("lineno"))# 将字节转换为合适的单位(如 MiB)total_size_mib = total_size / (1024 * 1024)logger.info(f"读取文件后,总内存分配: {total_size_mib:.2f} MiB")#image_urls = []file_infos : List[schemas.PPtToImage] = []for index, image in enumerate(images):image_path = os.path.join(output_folder, f"page_{index + 1}.png")image.save(image_path, "PNG")# 上传图像到COSurl = ""file_name = os.path.basename(image_path)image_key = new_file_name(file_name, space_id)if len(image_key) > FILE_NAME_MAX_LENGTH:image_key = image_key[:FILE_NAME_MAX_LENGTH]cosclient.put_object_file(image_path, image_key)url = cosclient.get_presigned_url(image_key)file_infos.append(schemas.PPtToImage(image_name=image_key, image_url=url))logger.info(f"Uploaded {image_path} to {image_key}")# 删除临时文件夹for image_filename in os.listdir(output_folder):# 验证文件名是否安全if is_safe_filename(image_filename):# 如果文件名安全,则删除文件os.unlink(os.path.join(output_folder, image_filename))else:# 如果文件名不安全,记录日志并跳过删除操作logger.warning(f"Unsafe filename detected: {image_filename}. Skipping deletion.")os.rmdir(output_folder)return file_infos

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/56842.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞机大战告尾

参考 PPO算法逐行代码详解 链接 通过网盘分享的文件:PlaneWar 链接: https://pan.baidu.com/s/1cbLKTcBxL6Aem3WkyDtPzg?pwd1234 提取码: 1234 10.17关于博客发了又改这件事 悲催的事 今天训练了一早上ppo模型,满怀期待的检测成果时发现一点长进都…

【Linux】“echo $变量“ 命令打印变量值的底层原理

在 shell 中,echo $变量 命令的工作原理涉及几个关键步骤,主要是由 shell 解释器来处理变量的查找和替换。以下是详细的过程: 变量展开的过程顺序 变量引用: 在命令行中,变量通常以 $variable_name 或 ${variable_…

使用Shell脚本对Java应用等服务进行启停控制(支持批量)

通过shell脚本对Java服务启停进行控制。支持单个服务和多个服务的 start、stop、status、restart。支持自定义启动命令。(不限于Java服务,适用于各类通过命令行启动的服务) 脚本名称为 runjar.sh , 底部提供源码。通过三部分进行说明:操作说明、维护自定义服务列表、脚本源…

搭建`mongodb`副本集-开启权限认证 mongo:7.0.5

搭建mongodb副本集-开启权限认证 mongo:7.0.5 1.5.1、创建文件 创建配置文件保存目录和数据保存目录 mkdir -p /data/mongodb/{/conf,/data,/logs}生成和设置权限 这个文件一定要在一个服务里面生成然后复制到其它服务器,所有服务器的这个key一定是相同的。 op…

C语言 | Leetcode C语言题解之第480题滑动窗口中位数

题目: 题解: struct Heap {int* heap;int heapSize;int realSize;bool (*cmp)(int, int); };void init(struct Heap* obj, int n, bool (*cmp)(int, int)) {obj->heap malloc(sizeof(int) * (n 1));obj->heapSize 0;obj->cmp cmp; }bool c…

第二十二篇——菲欧几何:相对论的数学基础是什么?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 对于几何的几个工具,让我再次感叹数学的伟大,逻辑…

国产大模型基础能力大比拼 - 计数:通义千文 vs 文心一言 vs 智谱 vs 讯飞-正经应用场景的 LLM 逻辑测试

在大语言模型(LLM)不断涌现的时代,如何评估这些国产大模型的逻辑推理能力,尤其是在处理基础计数问题上的表现,成为了一个备受关注的话题。随着越来越多的国产大模型进入市场,比较它们在不同任务中的表现尤为…

STM32笔记(1)GPIO之点亮LED

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 总结 第一步:先看原理图。PB0输出高电平是,LED1点亮。 初始化完成了两项工作: (1)从时钟上启动所用GPIO所在的总线&#xff1b…

Centos7 安装升级最新版Redis7.4.1

1. 前言 今天阿里云云盾检测出一个redis低版本的漏洞,需要升级到稳定高版本修复漏洞,升级过程遇到了一些坑,特记录分享给大家,原服务器默认yum源安装的gcc 是4.8.5 ,默认安装redis是 3.2.12(如下图): 2.升级GCC 升级新版redis需要更高级的gcc支持,这里我们就选择升级…

《计算机视觉》—— 换脸

效果如下: 完整代码: import cv2 import dlib import numpy as npJAW_POINTS list(range(0, 17)) RIGHT_BROW_POINTS list(range(17, 22)) LEFT_BROW_POINTS list(range(22, 27)) NOSE_POINTS list(range(27, 35)) RIGHT_EYE_POINTS list(range(36…

力扣 中等 82.删除排序链表中的重复元素 II

文章目录 题目介绍题解 题目介绍 题解 只需在83题基础上加一个while循环即可 class Solution {public ListNode deleteDuplicates(ListNode head) {ListNode dummy new ListNode(101, head);ListNode cur dummy;while (cur.next ! null && cur.next.next ! null) {…

【Linux】Anaconda下载安装配置Pytorch安装配置(保姆级)

目录 Anaconda下载 Anaconda安装 conda init conda --v Conda 配置 conda 环境创建 conda info --envs conda list Pytorch安装配置 检验安装情况 检验是否可以使用GPU Anaconda下载 可以通过两种途径完成Anaconda安装包的下载 途径一:本地windows下…

运算放大器的带宽

运算放大器(Op-Amp)的带宽是指放大器能够稳定放大信号而不发生增益衰减的最高频率范围。带宽通常定义为放大器增益下降3分贝(dB)时对应的频率,这个点也被称为-3dB点(下图中是蓝色方框圈出的点)。…

读数据工程之道:设计和构建健壮的数据系统13无服务器

1. 无服务器 1.1. 云供应商的一个大趋势是无服务器,允许开发人员和数据工程师无须在后台管理服务器即可运行应用程序 1.1.1. 无服务器快速将价值投入到其正确的用例 1.2. 无服务器真正开始流行是在2014年AWS Lambda全面投入使用…

C++ —— 类和对象

目录 介绍类和对象 一. 类和对象——类的定义 1.访问限定符 2.类域 作用操作符:: 3.对象大小 类的实例化 内存对齐规则 4.this指针 this指针会出现的问题 5.C语言结构体与C类对比 封装的本质 C类的优点 二 .类和对象——关于成员 1.类的默认成员函数 I.构造函数 构…

SpringBoot+Vue+Uniapp智能社区服务小程序系统(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

三菱FX3U-4AD模块怎样读出模拟量数据的?

关于使用FX3U-4AD读出模拟量数据时,所需的最低限度的程序,就此进行说明。读出模拟量数据的步骤如下所示: 1、确认单元号 从左侧的特殊功能单元/模块开始,依次分配单元号0~7。连接在FX3UC-32MT-LT(-2)可编程控制器上时&#xff0c…

ubuntu24.0离线安装Ollama和纯cpu版本以及对接Spring AI

文章目录 一.官网下载 0.3.13版本二.将文件包上传至ubuntu服务器三.下载安装脚本四.剔除GPU相关下载ROCM等,纯CPU运行脚本五.ollama常用命令六. 远程测试 七.对接spring AI 一.官网下载 0.3.13版本 ollama离线安装包下载地址 二.将文件包上传至ubuntu服务器 三.下…

电感电容谐振原理及Matlab仿真

一、电感电容谐振原理概述 电感电容谐振(LC谐振)是一种电路现象,它发生在电感器(L)和电容器(C)通过适当的方式连接时,电路中电流和电压之间形成共振。在这种共振状态下,…

计算机组成原理与系统结构——外部存储器

笔记内容及图片整理自XJTUSE “计算机组成原理与系统结构” 课程ppt,仅供学习交流使用,谢谢。 磁盘 磁盘是一个由非磁性材料构成的圆形盘片(称为基片),上面涂抹可磁化材料。传统的基片一直是铝制或铝合金的&#xff0…