# video-uploader-demo **Repository Path**: kevinleeeee/video-uploader-demo ## Basic Information - **Project Name**: video-uploader-demo - **Description**: 一个前后端实现的视频上传播放器 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-07-20 - **Last Updated**: 2022-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 视频操作 ## 概述 考虑到访问量和带宽需要,视频要以云存储等公有服务商提供服务支持,云服务器具有分布式,设置,构建,串联等庞大的优势,非常有能力去处理大文件和大视频的处理,云存储服务商有相应的`API`去对视频切片,且有规格限制视频的格式(`720p`, `1080p`, `2k`, `4k`...) 对视频的处理是非常复杂的,对视频切片相对较于简单,但是对规格处理就比较难,且其中视频的优化也是比较难的,需要相应的算法去处理,到了商用阶段,视频处理理应是通过云存储服务商来处理的,并且提供存储的方案,最后提供处理好的视频数据 开发者仅需从服务商提供的数据中知道: - 云存储绑定的域名 - 对应格式的视频文件名 - 加速器 前端需要做: 1. 获取处理好的结果的视频数据 2. 获取加速器域名 3. 将域名和数据存入数据库 4. 从数据库提取信息调取视频 5. 将数据库信息拼接为`url`地址 6. `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
//js var 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); //监听onload xhr.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: 在您的快速服务器请求中,您可以从以下位置访问您上传的文件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: , * size: 65536, //上传大小(以字节为单位) * encoding: '7bit', * tempFilePath: '', * truncated: false, //表示文件是否超过大小限制 * mimetype: 'application/octet-stream', * md5: '7c8a439ddc4164dc28ea624cf6c8a7fa', //上传文件的 MD5 校验 * mv: [Function: mv] * } */ ``` ## 流程 上传一个文件的流程有: 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`的切片`chunk`的`ts`文件,`m3u8`对应的是一种`hls`视频流的类型 12. 将存储`m3u8`文件集合的文件夹`folder`设置为可通过域名访问的静态文件目录`static folder`的后端`backend folder` 13. 向前端返回一个可访问的`url`地址(`http://www.xxx.com/test/file1.mp4`) 14. 前端播放器播放时逐一请求对应的`ts`文件块而进行切片播放 > **补:** 除了通过`formData`的形式去上传,还可以通过二进制的方式,二进制将其字符转为`buffer`,目的是为了切片对象`blob` ## 文档 - [西瓜播放器](https://v2.h5player.bytedance.com/gettingStarted/) - [ffmpeg官网](https://ffmpeg.org/) - [`node`服务器提供的`ffmpeg`包](https://www.npmjs.com/package/@ffmpeg-installer/ffmpeg) ## 功能 实现功能: - 单/多文件选择 - 上传视频 会显示进度读条 - 上传视频过程可以暂停操作 - 上传视频过程可以取消暂停操作继续上传 - 格式切片上传 - 合并视频 - 断点 - 视频转码 - 转码后切片播放 ## 搭建 **前端搭建** ``` //初始化项目 npm init -y //安装vite npm i -D vite@2.9.13 //安装axios //安装qs //安装xgplayer插件依赖 npm i -D xgplayer@2.31.6 npm i -D xgplayer-hls@2.5.2 ``` **后端搭建** ``` //初始化项目 npm init -y //安装express npm i -S express@4.18.1 //安装加密crypto npm i -S crypto-js@4.1.1 //安装文件上传处理的库 npm i -S express-fileupload@1.4.0 //安装视频切片的库 npm i -S @ffmpeg-installer/ffmpeg@1.1.0 npm i -S fluent-ffmpeg@2.1.2 ``` ## 源码 **源码地址:** https://gitee.com/kevinleeeee/video-uploader-demo