媒资管理之视频管理

一:业务概述:

媒资管理这个模块是我负责开发的,主要的管理对象是视频,图片,文档等

包括文件的上传,视频的处理,文件的删除

(在媒资管理界面,有个上传视频的按钮,视频是在媒资这上传的,课程图片是在内容管理)

上传的图片和视频,会单独存储到搭建的分布式文件系统当中。

当上传视频时,视频比较大,如果我选择的是断点续传来进行上传,并且上传的视频不是都能直接播放的,要进行格式的转换,所以选择一个视频文件上传之后,会自动进行一个格式处理,最后还会进行视频与课程的绑定,这些做好之后,才可以发布一个课程。

二:工作内容

在这个系统中,我一共设计了三张表:分别是媒资文件表,待处理文件表,历史处理文件表。

媒资文件表保存了上传文件的详细信息,比如文件名称,文件类型(图片,文档,视频),存储目录,文件存储路径,文件访问url(针对于图片来说,存储路径和url一致,但是视频的存储路径是avi,而访问url是MP4格式),文件id(md5),等

待处理文件表保存了文件名称,状态,访问地址,失败信息等

历史处理文件表保存了文件名称,状态等

在这里面,我主要给您讲一下视频的上传与处理您看可以吗?

当视频上传之后,会将视频保存到minio这个系统当中

(因为minio系统比较轻量,操作简单,免费,而且可以保证数据安全,不会丢失)

(保证不丢失,是因为它保存的数据,是分块存储的,不会全部保存到一个硬盘上,并且还有备份)

在使用它之前,在程序中添加它的一个依赖,它提供了示例方法,用来进行上传,删除和下载,在程序当中去使用它提供的方法,在方法中依靠它的核心逻辑,进行改造,实现我们想要的功能。

上传是需要先初始化出一个minio对象,在客户端创建出一个bucket,相当于一个文件夹,用来保存上传过来的数据,然后针对于这些大文件的上传,就要进行断点续传了,在文件上传前要对文件进行检查,分块文件上传之前,也要进行检查,检查完就去上传分块,所以分块上传完后,就合并这些分块,最后将相关信息写入到媒资服务中的文件表中,还要向待处理视频表中添加相关信息,比如文件名称,存储位置,失败次数为0,当前状态设置为未处理。上传成功之后,还需要对视频进行转码,我使用的是ffmpeg进行视频转码,为了能够提高效率吧,我使用了一个叫xxl-job的一个工具,进行任务调度,所以当把相关信息写入到待处理文件表后,调度中心就向执行器发起任务调度去执行转码任务,如果执行成功,去文件表中更新视频的url,去待处理任务表中更新文件的状态,完成时间,复制这条记录,把这条记录,再插入到历史纪录表,删除掉待处理任务表中的这个任务,但是如果执行失败,就在待处理任务表中添加失败原因,失败次数,任务状态

您看我要不要给您说一下我这个断点续传是咋实现的?

前端会对文件进行分块处理;

再一块一块的进行上传,在上传之前,会对文件进行检查,是否存在,如果不存在,会选择继续上传分块,分块在上传之前,也会进行检查,看是否上传过,如果上传过,则不上传此分块,继续下一分块,直到分块全部上传完成,会对分块进行合并,合并完成之后,将文件的相关信息写入到文件表中

但是上传之后的视频格式如果不是MP4类型的,就不能直接播放,所以我使用了FFmpeg这个工具,进行格式转换,但是由于视频的大小一般是很大的,并且数量也多,所以为了节省时间和提高效率,我使用了xxl-job这个分布式任务调度,去调度执行视频转码这个需求

在服务里面写出任务方法,并且用xxljob的注解去标记这个任务;

在调度中心就可以去配置一下任务调度的策略,隔多长时间去调度一次,还是固定时间去调度

就可以在调度中心去启动任务了,

调度中心根据任务调度策略,到达时间就发送调度请求给执行器

执行器接收到请求后,就开始处理任务。

三:相关问题

1:上传之后,你返回数据用的什么类?

用的dto类,继承了文件类。

2:上传文件,你用的什么接收文件?

用的multipartfile这个类型接收文件

3:在service层,你用什么接收文件信息?

创建了dto类,用来接收文件信息,包括文件名称,上传人,文件类型等

4:你要给services层传什么参数?

因为要上传嘛,所以要传文件的本地路径,文件名字,文件信息

5:你在客户端是如何存储的文件?

在进行上传的时候,会上传对象名,客户端会根据对象名来创建子目录,存放文件的

6:你是以什么格式来存储的呢?

以年月日的格式创建子目录,进行存放,方便查找数据

7:那你是如何获取当前时间的?

使用了一个获取时间的类,获取完之后,对时间格式进行了操作,以斜杠的形式分割年月日,这样客户端会创建出对应的子目录。

8:上传的文件的文件名会不会重复?重复之后怎么办呢

如果文件名重复,会发生覆盖,所以为了避免这个问题,使用文件的md5值作为文件的名字

9:会不会上传失败?

可能会,上传任务完成会返回布尔值,会对布尔值进行判断。

10:在你保存信息到文件表中时,会不会文件已经存在于这个文件表了?

嗯,是有这种可能的,所以就需要先通过文件的id,先去查一下,对查出来的对象进行一下非空判断,为空的话,在进行插入操作。

11:那你是如何插入的呢?

先创建出一个mediafile对象,再使用beanutils的copy方法,为这个新对象赋值。

然后给新对象再设置一些值,比如文件id,桶的名称 ,文件地址也就是对象名,fileid(也就是md5值),url。

12:插入会不会失败?

会,所以对返回值判断,如果小于等于0,就打印日志

13:我看你那会说用到断点续传了,你介绍一下吧

因为视频文件会比较大,所以上传的时间会比较长,如果在这一段时间内,因为网络故障的原因,导致上传失败了,就需要重新开始上传,这样比较浪费时间,使用断点续传后,就可以从上一次结束的时候继续上传。

14:那你在项目中是如何使用的呢?

主要逻辑是把一整块文件呢,分成多个小块进行上传

具体做法是首先需要先检验一下要上传的文件是否存在,如果存在就不必重新上传了,

如果不存在,前端将文件分成块后,在进行上传前,会对块进行校验,如果存在,前端就不用上传,继续下一块。        

全部上传完毕后,就将所有分块进行合并,

同时合并之后,要对这个文件进行检验,看是否完整,具体做法是将新文件的md5值与旧文件的md5值进行比较,如果相等,就是完整的,否则就是不完整。

15:对于检验文件是否存在是怎么做的?

主要看是不是存在,如果存在,就不上传了。

我是先对数据库中检验,看看是否有有这个文件,拿着文件的id,也就是md5值进行查询,进行非空判断,如果是空的,就返回false,让前端传来数据,如果是非空,也不要掉以轻心,可能是脏数据,还得去查一下minio中是否有这个文件,先通过文件的相关信息,调用get方法,获取一个流对象,对这个流对象进行非空判断,如果为空就返回false,让前端传文件,如果不为空,返回true。

16:检验分块文件你是怎么做的呢?

我设计的是拿着文件的md5值和这个分块文件的序号就可以在minio中查找这个分块文件

因为分块文件在minio的存储目录是以md5的前两位数字作为目录的,序号是文件的名字

通过这md5和序号,可以构造出这个分块文件的存储路径,通过minio对象的get方法即可获得一个流对象,通过对这个流对象进行非空判断即可。

17:上传分块你是怎么做的?

我是通过传来的md5值和序号做出这个分块文件的存储路径,调用minio对象的upload方法进行上传,上传失败会抛出异常,返回false。

18:合并分块是怎么做的?

先找到分块文件,再调用minio对象sdk进行合并,合并完,获取合并后的文件和原文件的md5,进行比较,看是否相等,相等则文件完整,则将文件的相关信息写入到文件表中。

19:再具体一点是怎么合并的呢?

指定出每个分块文件的信息,也就是在minio中的哪个桶,序号是几,

再指定出合并后的文件的存储路径和名字,把这些信息综合起来,传给minio对象的合并方法即可。

20:合并文件的名字是一个一个起吗?

是进行统一设置的,以文件的MD5值为文件名字。

21:存入文件表存的什么呢?

文件的相关信息,文件名称,文件的存储路径,文件的md5值等等

22:为什么要进行视频转码?

因为用户上传的视频格式,可能无法直接播放,格式也可能不统一,所以进行视频转码,全部转变为一种统一的MP4格式。

编码标准是h264,音频是aac。

23:那你跟我说一下什么是分布式任务调度吧?

任务调度就是设置一个固定时间间隔,去自动执行任务。

分布式任务调度就是用多个节点去执行分配的任务。

24:调度中心有什么?

调度中心和执行器。调度中心是下发任务的,是领导者,而执行器是负责接收命令的,负责干活的

25:你为什么使用这个xxl-job呢

因为他使用起来很方便,配置也不麻烦

能够对任务进行统一管理和调度;

并且比较稳定,并且开源;

26:你是如何保证任务不会被重复执行的呢?

27:运行模式是什么呢?

可以单个执行器运行,也可以多个执行器同时进行,就是使用分片广播的方式

广播的意思就是调度中心会向所有执行器发送任务调度,同时发送分片参数

分片参数包括执行器总数和执行器起始序号

分片的意思是以一个执行器为单位,进行分片,给每个执行器标上序号,执行器根据自己的序号去处理自己负责的任务。

28:那你具体跟我说一下执行器是怎么执行任务的呢?

先去领取任务,也就是在待处理文件表中进行查询状态为未处理的任务,但是每个执行器他查询到的任务是不同的,因为要让多个执行器同时执行不同的任务,提高效率

29:如何实现任务不同的呢?

调度中心在发起请求时,会给每个执行器发送分片参数,包括执行器总数,和分片序号,会告诉执行器,他的序号是几?通过任务id除以序号的余数是几,谁就执行这个任务。

30:什么叫分布式锁?

一个锁不是被一个虚拟机共享,而是被多个虚拟机共享

31:如何使用的分布式锁?

使用的是乐观锁的思想,给状态添加一个值,为处理中,谁成功设置为了处理中,谁就相当于拿到了这把锁。

32:那谁都可以更改阿?

添加一个条件,当状态为未处理或者为处理失败时,可以更改为处理中。

33:多线程在哪里用到了

针对于视频处理的时候用到了,用来同时处理多个视频

34:怎么用的?

先创建出一个线程池

调用threadpol的execute方法,在这个线程池中

将视频转码,把处理完的视频上传到minio中,更新任务状态。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容