跳到主要内容

数字人需求总结

· 阅读需 5 分钟

最近做了个数字人相关的需求,感觉有点意思,就随便写点。

我们有主讲老师和辅导老师,主讲老师是负责讲课的,而辅导老师主要是提供课后辅导等服务。在进行课后辅导的过程中,有时辅导老师也需要讲课,但讲课并不是辅导老师的强项,而如果在讲课时直接使用主讲老师的视频又会在辅导过程中产生割裂感。因此,可以使用数字人的技术,让辅导老师的“数字分身”来讲课。数字人讲课视频的制作流程如下:

image

例如,揭开氧化还原反应神秘面纱 是一个主讲老师录制的讲课视频,25暑新高一化学预习视频3 是使用数字人技术制作的辅导老师的讲课视频,它是通过主讲老师的讲课视频与辅导老师录制的一段视频制作的。

技术设计

首先是库表设计,只使用一张表,用于存储上传的视频、产出的视频、中间产物等资源的信息。

CREATE TABLE `tblDigitalAssetMeta` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`type` int(11) NOT NULL DEFAULT '0' COMMENT '资源类型 1:员工录制AI形象音视频 2:从音视频提取的视频 3:从音视频提取并编码的音频 4:课件讲题音视频 7:音色替换克隆音频 8:数字人音视频 9:合成数字人课件讲题音视频',
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
`biz_info` varchar(8000) NOT NULL DEFAULT '' COMMENT '资源的业务属性信息,与type有关',
`search_key` varchar(1000) NOT NULL DEFAULT '' COMMENT '搜索key',
`prev_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '资源的前驱',
`obj_id` varchar(500) NOT NULL DEFAULT '' COMMENT '对象id,在对象存储中的存储路径',
`task_id` varchar(255) NOT NULL DEFAULT '' COMMENT '任务id',
`task_status` int(11) NOT NULL DEFAULT '0' COMMENT '任务状态 0:无任务 1:待执行 2:执行中 3:执行成功 4:执行失败 5:手动取消',
`task_info` varchar(8000) NOT NULL DEFAULT '' COMMENT '任务信息',
`err_msg` varchar(255) NOT NULL DEFAULT '' COMMENT '错误信息',
`deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否已删除 0:未删除 1:已删除',
`creator` bigint(20) NOT NULL DEFAULT '0' COMMENT '创建者',
`updater` bigint(20) NOT NULL DEFAULT '0' COMMENT '更新者',
`create_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '创建时间',
`update_time` bigint(20) NOT NULL DEFAULT '0' COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_t_d_ct` (`type`,`deleted`,`create_time`),
KEY `idx_c_ct` (`creator`,`create_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='数字化媒体资源元数据表'

核心的实现是将整个过程抽象成有向无环图(DAG)。除了上传的内容,其余内容都是通过任务生产的。对于DAG中的节点,先检查其前驱是否都已就绪,如果没有则等待前驱就绪,如果前驱已就绪就执行生产任务。

DAG通过MQ消息驱动,我设计了4种MQ消息:Flow、Run、Check、Callback,下面说下这些的作用。

Flow

当提交创建数字人讲课视频的任务时,会向数据库中插入数字人讲课视频的资源节点,同时发出该节点的Flow的MQ消息。在消费Flow消息时,会构建需要的资源节点,并设置相应的前驱,从而构建出DAG。对于数字人讲课视频而言,会先检查是否已完成音频分离,如果已完成就服用之前的资源节点,否则会创建分离的音频的资源节点;然后会构建克隆的声音的资源节点,然后设置好各资源节点的前驱;最后,对于需要任务生产的资源节点,向MQ发出对应的Run消息。

Run

在消费Run消息时,会先检查前驱是否已就绪。如果前驱尚未就绪,就发个延时的Run消息来进行重试;如果有前驱失败,那么当前任务也失败;如果前驱都已就绪,那么就可以执行任务了。在执行前会发送延时的Check消息,用来检查任务的执行结果。

Check

Check消息可以检查任务的执行结果,如果还未执行完毕,就再发个延时的Check消息来进行重试。

Callback

除了通过Check消息轮询的方式来检查任务的执行结果,也可以通过回调来通知任务的执行结果。在触发回调时,就会发送Callback消息。

遇到的问题

音视频分离和最后的视频合成是由我这边完成的,我在Docker中塞了个ffmpeg。视频合成非常消耗CPU,而当CPU使用率超过50%就会触发告警,因此需要对ffmpeg的CPU使用率加以控制。我尝试过-threads 1 选项也不行,-x264-params threads=1 选项还是不行,最后发现可以使用cpulimit 这个工具,它可以控制CPU使用率,它的实现方式是向进程发送SIGSTOPSIGCONT信号。

image

使用之后,CPU使用率控制在了50%以下,40%以上,既不会触发告警也不至于使用率过低。