视频操作
概述
考虑到访问量和带宽需要,视频要以云存储等公有服务商提供服务支持,云服务器具有分布式,设置,构建,串联等庞大的优势,非常有能力去处理大文件和大视频的处理,云存储服务商有相应的API去对视频切片,且有规格限制视频的格式(720p, 1080p, 2k, 4k…)
对视频的处理是非常复杂的,对视频切片相对较于简单,但是对规格处理就比较难,且其中视频的优化也是比较难的,需要相应的算法去处理,到了商用阶段,视频处理理应是通过云存储服务商来处理的,并且提供存储的方案,最后提供处理好的视频数据
开发者仅需从服务商提供的数据中知道:
- 云存储绑定的域名
- 对应格式的视频文件名
- 加速器
前端需要做:
- 获取处理好的结果的视频数据
- 获取加速器域名
- 将域名和数据存入数据库
- 从数据库提取信息调取视频
- 将数据库信息拼接为
url地址 url地址返回前端进行是视频播放
Q&A
当上传文件时会存在什么问题?
当处理大文件时网络传输会造成时间耗费,时间会对网络请求进行阻塞,阻塞会造成没有足够的响应,网络请求是无状态的,当前请求当前响应,文件没有上传成功时是不会有响应的,而且每次的请求是独立的,没有状态联系的,所以会有大量的时间在等待,也无法得知上传的进度和上传的时间和后端是否正确的上传成功
如何解决上传问题?
对大文件进行裁切slice,切片成一个小块chunk,并逐一按顺序同步上传至后端
什么是FFmpeg?
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的
FormData是什么?
XMLHttpRequest是一个浏览器接口,通过它,我们可以使得 Javascript进行HTTP (S) 通信。XMLHttpRequest在现在浏览器中是一种常用的前后台交互数据的方式。
2008年 2 月,XMLHttpRequest Level 2 草案提出来了,相对于上一代,它有一些新的特性,其中 FormData就是XMLHttpRequest Level 2新增的一个对象,利用它来提交表单、模拟表单提交,当然最大的优势就是可以上传二进制文件。
formData对象模拟HTML表单,相当于将HTML表单映射成表单对象,自动将表单对象中的数据拼接成请求参数的格式。并且可以异步上传二进制文件。
FormData接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send() 方法发送出去,它是一个构造函数, 需要new FormData()创建
//html<form id="form"><input type="text" name="username" /><input type="password" name="password" /><input type="button" value="submit" id="submitBtn"/></form>//jsvar submitBtn = document.getElementById('submitBtn');var form = document.getElementById('form');submitBtn.onclick = funtion(){//将html表单转为表单对象var formData = new FormData(form);//创建ajax对象var xhr = new XMLHttpRequest();//配置xhr.open('post', 'http://localhost:3000/formData');//发送ajax请求xhr.send(formData);//监听onloadxhr.onload = function(){if(xhr.status === 200){ console.log(xhr.response); }}}
FormData构造函数里有什么方法?
//向 FormData 中添加新的属性值,FormData 对应的属性值存在也不会覆盖原值,而是新增一个值,如果属性不存在则新增一项属性值FormData.append()//从 FormData 对象里面删除一个键值对FormData.delete()//返回一个包含所有键值对的iterator对象FormData.entries()//返回在 FormData 对象中与给定键关联的第一个值FormData.get()//返回一个包含 FormData 对象中与给定键关联的所有值的数组FormData.getAll()//返回一个布尔值表明 FormData 对象是否包含某些键FormData.has()//返回一个包含所有键的iterator对象FormData.keys()//给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值FormData.set()//返回一个包含所有值的iterator对象FormData.values()
express-fileupload是什么?
用于上传文件的简单快速中间件。
express-fileupload如何使用?
当您上传文件时,该文件将可以从req.files中获取信息
//例子:您正在上传一个名为car.jpg的文件您输入的名称字段是foo:<input name="foo" type="file" />在您的快速服务器请求中,您可以从以下位置访问您上传的文件req.files.foo:app.post('/upload', function(req, res) {console.log(req.files.foo); // the uploaded file object});/**打印返回的一个req.files.foo对象console.log(req.files);* foo: {* name: 'blob',* data: <Buffer c9 1f 00 ... 65486 more bytes>,* size: 65536, //上传大小(以字节为单位)* encoding: '7bit',* tempFilePath: '',* truncated: false, //表示文件是否超过大小限制* mimetype: 'application/octet-stream',* md5: '7c8a439ddc4164dc28ea624cf6c8a7fa', //上传文件的 MD5 校验* mv: [Function: mv]* }*/
流程
上传一个文件的流程有:
- 选择文件
input type="file" file.value是一个file类型文件其实也是new File的实例- 将
file实例放入formData表单格式去上传(需要处理大文件) - 将
formData进行裁切为chunk - 将多个
chunk按顺序逐一上传至后端 - 后端接收
chunk文件,并获取里面的信息如size,name,type - 将上传信息(
uploading information)保存至数据库(database)里 - 将单个文件的所有
chunks单独保存到一个临时目录,等待上传完毕 - 将所有的
chunks合并(merge)并写入成一个文件如mp4文件 - 转码操作,将写好的文件又通过第三方库去格式化
split为相应规格的格式(如转码720p需要的m3u8文件类型) m3u8文件会调用mp4的切片chunk的ts文件,m3u8对应的是一种hls视频流的类型- 将存储
m3u8文件集合的文件夹folder设置为可通过域名访问的静态文件目录static folder的后端backend folder - 向前端返回一个可访问的
url地址(http://www.xxx.com/test/file1.mp4) - 前端播放器播放时逐一请求对应的
ts文件块而进行切片播放
补: 除了通过
formData的形式去上传,还可以通过二进制的方式,二进制将其字符转为buffer,目的是为了切片对象blob
文档
功能
实现功能:
单/多文件选择
上传视频 会显示进度读条
上传视频过程可以暂停操作
上传视频过程可以取消暂停操作继续上传
格式切片上传
合并视频
断点
视频转码
转码后切片播放
搭建
前端搭建
//初始化项目npm init -y//安装vitenpm i -D vite@2.9.13//安装axios//安装qs//安装xgplayer插件依赖npm i -D xgplayer@2.31.6npm i -D xgplayer-hls@2.5.2
后端搭建
//初始化项目npm init -y//安装expressnpm i -S express@4.18.1//安装加密cryptonpm i -S crypto-js@4.1.1//安装文件上传处理的库npm i -S express-fileupload@1.4.0//安装视频切片的库npm i -S @ffmpeg-installer/ffmpeg@1.1.0npm i -S fluent-ffmpeg@2.1.2
源码
源码地址:
