视频操作

概述

考虑到访问量和带宽需要,视频要以云存储等公有服务商提供服务支持,云服务器具有分布式,设置,构建,串联等庞大的优势,非常有能力去处理大文件和大视频的处理,云存储服务商有相应的API去对视频切片,且有规格限制视频的格式(720p, 1080p, 2k, 4k…)

对视频的处理是非常复杂的,对视频切片相对较于简单,但是对规格处理就比较难,且其中视频的优化也是比较难的,需要相应的算法去处理,到了商用阶段,视频处理理应是通过云存储服务商来处理的,并且提供存储的方案,最后提供处理好的视频数据

开发者仅需从服务商提供的数据中知道:

  • 云存储绑定的域名
  • 对应格式的视频文件名
  • 加速器

前端需要做:

  1. 获取处理好的结果的视频数据
  2. 获取加速器域名
  3. 将域名和数据存入数据库
  4. 从数据库提取信息调取视频
  5. 将数据库信息拼接为url地址
  6. url地址返回前端进行是视频播放

Q&A

当上传文件时会存在什么问题?

当处理大文件时网络传输会造成时间耗费,时间会对网络请求进行阻塞,阻塞会造成没有足够的响应,网络请求是无状态的,当前请求当前响应,文件没有上传成功时是不会有响应的,而且每次的请求是独立的,没有状态联系的,所以会有大量的时间在等待,也无法得知上传的进度和上传的时间和后端是否正确的上传成功

如何解决上传问题?

对大文件进行裁切slice,切片成一个小块chunk,并逐一按顺序同步上传至后端

什么是FFmpeg

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPLGPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库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()创建

  1. //html
  2. <form id="form">
  3. <input type="text" name="username" />
  4. <input type="password" name="password" />
  5. <input type="button" value="submit" id="submitBtn"/>
  6. </form>
  7. //js
  8. var submitBtn = document.getElementById('submitBtn');
  9. var form = document.getElementById('form');
  10. submitBtn.onclick = funtion(){
  11. //将html表单转为表单对象
  12. var formData = new FormData(form);
  13. //创建ajax对象
  14. var xhr = new XMLHttpRequest();
  15. //配置
  16. xhr.open('post', 'http://localhost:3000/formData');
  17. //发送ajax请求
  18. xhr.send(formData);
  19. //监听onload
  20. xhr.onload = function(){
  21. if(xhr.status === 200){ console.log(xhr.response); }
  22. }
  23. }

FormData构造函数里有什么方法?

  1. //向 FormData 中添加新的属性值,FormData 对应的属性值存在也不会覆盖原值,而是新增一个值,如果属性不存在则新增一项属性值
  2. FormData.append()
  3. //从 FormData 对象里面删除一个键值对
  4. FormData.delete()
  5. //返回一个包含所有键值对的iterator对象
  6. FormData.entries()
  7. //返回在 FormData 对象中与给定键关联的第一个值
  8. FormData.get()
  9. //返回一个包含 FormData 对象中与给定键关联的所有值的数组
  10. FormData.getAll()
  11. //返回一个布尔值表明 FormData 对象是否包含某些键
  12. FormData.has()
  13. //返回一个包含所有键的iterator对象
  14. FormData.keys()
  15. //给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值
  16. FormData.set()
  17. //返回一个包含所有值的iterator对象
  18. FormData.values()

express-fileupload是什么?

用于上传文件的简单快速中间件。

express-fileupload如何使用?

当您上传文件时,该文件将可以从req.files中获取信息

  1. //例子:
  2. 您正在上传一个名为car.jpg的文件
  3. 您输入的名称字段是foo:<input name="foo" type="file" />
  4. 在您的快速服务器请求中,您可以从以下位置访问您上传的文件req.files.foo
  5. app.post('/upload', function(req, res) {
  6. console.log(req.files.foo); // the uploaded file object
  7. });
  8. /**
  9. 打印返回的一个req.files.foo对象
  10. console.log(req.files);
  11. * foo: {
  12. * name: 'blob',
  13. * data: <Buffer c9 1f 00 ... 65486 more bytes>,
  14. * size: 65536, //上传大小(以字节为单位)
  15. * encoding: '7bit',
  16. * tempFilePath: '',
  17. * truncated: false, //表示文件是否超过大小限制
  18. * mimetype: 'application/octet-stream',
  19. * md5: '7c8a439ddc4164dc28ea624cf6c8a7fa', //上传文件的 MD5 校验
  20. * mv: [Function: mv]
  21. * }
  22. */

流程

上传一个文件的流程有:

  1. 选择文件input type="file"
  2. file.value是一个file类型文件其实也是new File的实例
  3. file实例放入formData表单格式去上传(需要处理大文件)
  4. formData进行裁切为chunk
  5. 将多个chunk按顺序逐一上传至后端
  6. 后端接收chunk文件,并获取里面的信息如size,name,type
  7. 将上传信息(uploading information)保存至数据库(database)里
  8. 将单个文件的所有chunks单独保存到一个临时目录,等待上传完毕
  9. 将所有的chunks合并(merge)并写入成一个文件如mp4文件
  10. 转码操作,将写好的文件又通过第三方库去格式化split为相应规格的格式(如转码720p需要的m3u8文件类型)
  11. m3u8文件会调用mp4的切片chunkts文件,m3u8对应的是一种hls视频流的类型
  12. 将存储m3u8文件集合的文件夹folder设置为可通过域名访问的静态文件目录static folder的后端backend folder
  13. 向前端返回一个可访问的url地址(http://www.xxx.com/test/file1.mp4)
  14. 前端播放器播放时逐一请求对应的ts文件块而进行切片播放

补: 除了通过formData的形式去上传,还可以通过二进制的方式,二进制将其字符转为buffer,目的是为了切片对象blob

文档

功能

实现功能:

  • 单/多文件选择

  • 上传视频 会显示进度读条

  • 上传视频过程可以暂停操作

  • 上传视频过程可以取消暂停操作继续上传

  • 格式切片上传

  • 合并视频

  • 断点

  • 视频转码

  • 转码后切片播放

搭建

前端搭建

  1. //初始化项目
  2. npm init -y
  3. //安装vite
  4. npm i -D vite@2.9.13
  5. //安装axios
  6. //安装qs
  7. //安装xgplayer插件依赖
  8. npm i -D xgplayer@2.31.6
  9. npm i -D xgplayer-hls@2.5.2

后端搭建

  1. //初始化项目
  2. npm init -y
  3. //安装express
  4. npm i -S express@4.18.1
  5. //安装加密crypto
  6. npm i -S crypto-js@4.1.1
  7. //安装文件上传处理的库
  8. npm i -S express-fileupload@1.4.0
  9. //安装视频切片的库
  10. npm i -S @ffmpeg-installer/ffmpeg@1.1.0
  11. npm i -S fluent-ffmpeg@2.1.2

源码

源码地址:

https://gitee.com/kevinleeeee/video-uploader-demo