学成在线-第13天-讲义-在线学习 HLS 五

媒资管理 
前边章节完成在线视频播放,如何实现点击课程计划播放视频呢,课程视频如何管理呢? 
本节开始将对课程视频进行管理。 
6.1需求分析 
媒资管理系统是每个在线教育平台所必须具备的,百度百科对它的定义如下:
 
每个教学机构都可以在媒资系统管理自己的教学资源,包括:视频、教案等文件。 
目前媒资管理的主要管理对象是课程录播视频,包括:媒资文件的查询、视频上传、视频删除、视频处理等。 
媒资查询:教学机构查询自己所拥有的媒体文件。 
视频上传:将用户线下录制的教学视频上传到媒资系统。 
视频处理:视频上传成功,系统自动对视频进行编码处理。 
视频删除 :如果该视频已不再使用,可以从媒资系统删除。

下边是媒资系统与其它系统的交互情况:
 

1、上传媒资文件 
前端/客户端请求媒资系统上传文件。 
文件上传成功将文件存储到媒资服务器,将文件信息存储到数据库。 
2、使用媒资 
课程管理请求媒资系统查询媒资信息,将课程计划与媒资信息对应、存储。 
3、视频播放 
用户进入学习中心请求学习服务学习在线播放视频。 
学习服务校验用户资格通过后请求媒资系统获取视频地址。 
6.2 开发环境 
6.2.1 创建媒资数据库 
1、媒资文件信息

@Data
@ToString
@Document(collection = "media_file")
public class MediaFile {
/*
文件id、名称、大小、文件类型、文件状态(未上传、上传完成、上传失败)、上传时间、视频处理方式、视频处
理状态、hls_m3u8,hls_ts_list、课程视频信息(课程id、章节id)
*/
@Id
//文件id
private String fileId;
//文件名称
private String fileName;
//文件原始名称
private String fileOriginalName;
//文件路径
private String filePath;
//文件url
private String fileUrl;
//文件类型
private String fileType;
//mimetype
private String mimeType;
//文件大小
private Long fileSize;
//文件状态
private String fileStatus;
//上传时间
private Date uploadTime;
}

2、创建xc_media数据库 
媒资系统使用mongodb数据库存储媒资信息。
 

6.2.2 创建媒资服务工程 
媒资管理的相关功能单独在媒资服务中开发,下边创建媒资服务工程(xc-service-manage-media)。 
媒资服务的配置与cms类似,导入 资料”--xc-service-manage-media工程,工程结构如下:
 

6.3上传文件 
6.3.1 断点续传解决方案 
通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件的上传要求。http协议本身对上传文件大小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了,电断了没有上传完成,需要客户重新上传,这是致命的,所以对于大文件上传的要求最基本的是断点续传。
什么是断点续传: 
引用百度百科:断点续传指的是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传下载未完成的部分,而没有必要从头开始上传下载,断点续传可以提高节省操作时间,提高用户体验性。
如下图:

 
上传流程如下: 
1、上传前先把文件分成块 
2、一块一块的上传,上传中断后重新上传,已上传的分块则不用再上传 
3、各分块上传完成最后合并文件 
文件下载则同理。 
6.3.2 文件分块与合并 
为了更好的理解文件分块上传的原理,下边用java代码测试文件的分块与合并。 
6.3.2.1文件分块 
文件分块的流程如下: 
1、获取源文件长度 
2、根据设定的分块文件的大小计算出块数 
3、从源文件读数据依次向每一个块文件写数据。
//测试文件分块方法

@Test
public void testChunk() throws IOException {
File sourceFile = new File("F:/develop/ffmpeg/lucene.mp4");
// File sourceFile = new File("d:/logo.png");
String chunkPath = "F:/develop/ffmpeg/chunk/";
File chunkFolder = new File(chunkPath);
if(!chunkFolder.exists()){
chunkFolder.mkdirs();
}
//分块大小
long chunkSize = 1024*1024*1;
//分块数量
long chunkNum = (long) Math.ceil(sourceFile.length() * 1.0 / chunkSize );
if(chunkNum<=0){
chunkNum = 1;
}
//缓冲区大小
byte[] b = new byte[1024];
//使用RandomAccessFile访问文件
RandomAccessFile raf_read = new RandomAccessFile(sourceFile, "r");
//分块
for(int i=0;i<chunkNum;i++){
//创建分块文件
File file = new File(chunkPath+i);
boolean newFile = file.createNewFile();
if(newFile){
//向分块文件中写数据
RandomAccessFile raf_write = new RandomAccessFile(file, "rw");
int len = ‐1;
while((len = raf_read.read(b))!=‐1){
raf_write.write(b,0,len);
if(file.length()>chunkSize){
break;
}
}
raf_write.close();
}
}
raf_read.close();
}

6.3.2.2文件合并 
文件合并流程: 
1、找到要合并的文件并按文件合并的先后进行排序。 
2、创建合并文件 
3、依次从合并的文件中读取数据向合并文件写入数
//测试文件合并方法

@Test
public void testMerge() throws IOException {
//块文件目录
File chunkFolder = new File("F:/develop/ffmpeg/chunk/");
//合并文件
File mergeFile = new File("F:/develop/ffmpeg/lucene1.mp4");
if(mergeFile.exists()){
mergeFile.delete();
}
//创建新的合并文件
mergeFile.createNewFile();
//用于写文件
RandomAccessFile raf_write = new RandomAccessFile(mergeFile, "rw");
//指针指向文件顶端
raf_write.seek(0);
//缓冲区
byte[] b = new byte[1024];
//分块列表
File[] fileArray = chunkFolder.listFiles();
// 转成集合,便于排序
List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
// 从小到大排序
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return ‐1;
}
return 1;
}
});
//合并文件
for(File chunkFile:fileList){
RandomAccessFile raf_read = new RandomAccessFile(chunkFile,"rw");
int len = ‐1;
while((len=raf_read.read(b))!=‐1){
raf_write.write(b,0,len);
}
raf_read.close();
}
raf_write.close();
}

6.3.3 前端页面 
上传文件的页面内容参考:资料”--upload.vue文件 
6.3.3.1 WebUploader介绍 
如何在web页面实现断点续传? 
常见的方案有: 
1、通过Flash上传,比如SWFuploadUploadify
2、安装浏览器插件,变相的pc客户端,用的比较少。
3Html5 
随着html5的流行,本项目采用Html5完成文件分块上传。 
本项目使用WebUploader完成大文件上传功能的开发,WebUploader官网地址: 
http://fexteam.gz01.bdysite.com/webuploader/
 

使用WebUploader上传流程如下:

 
6.3.3.1 钩子方法 
webuploader中提供很多钩子方法,下边列出一些重要的:
 

本项目使用如下钩子方法: 
1before-send-fifile 
在开始对文件分块儿之前调用,可以做一些上传文件前的准备工作,比如检查文件目录是否创建完成等。

2before-send 
在上传文件分块之前调用此方法,可以请求服务端检查分块是否存在,如果已存在则此分块儿不再上传。 
3after-send-fifile 
在所有分块上传完成后触发,可以请求服务端合并分块文件。 
注册钩子方法源代码:

WebUploader.Uploader.register({
"before‐send‐file":"beforeSendFile",
"before‐send":"beforeSend",
"after‐send‐file":"afterSendFile"
}

6.3.3.2 构建WebUploader 
使用webUploader前需要创建webUploader对象。 
指定上传分块的地址:/api/media/upload/uploadchunk

// 创建uploader对象,配置参数
this.uploader = WebUploader.create(
{
swf:"/static/plugins/webuploader/dist/Uploader.swf",//上传文件的flash文件,浏览器不支持h5时启动
flash
server:"/api/media/upload/uploadchunk",//上传分块的服务端地址,注意跨域问题
fileVal:"file",//文件上传域的name
pick:"#picker",//指定选择文件的按钮容器
auto:false,//手动触发上传
disableGlobalDnd:true,//禁掉整个页面的拖拽功能
chunked:true,// 是否分块上传
chunkSize:1*1024*1024, // 分块大小(默认5M)
threads:3, // 开启多个线程(默认3个)
prepareNextFile:true// 允许在文件传输时提前把下一个文件准备好
}
)

6.3.3.3 before-send-fifile 
文件开始上传前前端请求服务端准备上传工作。 
参考源代码如下:

type:"POST",
url:"/api/media/upload/register",
data:{
// 文件唯一表示
fileMd5:this.fileMd5,
fileName: file.name,
fileSize:file.size,
mimetype:file.type,
fileExt:file.ext
}

6.3.3.4 before-send 
上传分块前前端请求服务端校验分块是否存在。 
参考源代码如下:

type:"POST",
url:"/api/media/upload/checkchunk",
data:{
// 文件唯一表示
fileMd5:this.fileMd5,
// 当前分块下标
chunk:block.chunk,
// 当前分块大小
chunkSize:block.end‐block.start
}

6.3.3.5 after-send-fifile 
在所有分块上传完成后触发,可以请求服务端合并分块文件 
参考代码如下:

type:"POST",
url:"/api/media/upload/mergechunks",
data:{
fileMd5:this.fileMd5,
fileName: file.name,
fileSize:file.size,
mimetype:file.type,
fileExt:file.ext
}

6.3.3.6 页面效果

发布了810 篇原创文章 · 获赞 150 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_40208605/article/details/104183528
HLS
今日推荐