0


前端Vue使用ffmpeg压缩视频再上传(全网唯一公开真正实现)

保姆级操作步骤,从我实际运行中的项目中摘取的所有相关代码展示如下:

1.Vue项目中安装插件ffmpeg

1.1 插件版本依赖配置

两个插件的版本 "@ffmpeg/core": "^0.10.0", "@ffmpeg/ffmpeg": "^0.10.1"
package.jsonpackage-lock.json 都加入如下ffmpeg的版本配置:

1.2 把ffmpeg安装(下载)到项目依赖目录里

terminal运行命令:

  1. npm i
  1. 或直接运行命令安装ffmpeg
  1. npm install @ffmpeg/ffmpeg @ffmpeg/core -S
  1. 安装后package-lock.json会自动写入如下配置:

1.2.1 报错处理

如果出现安装问题:

①先在npm i命令后加--legacy-peer-deps 或者 --force运行

  1. npm i --force

②如果上步不行,尝试删除这个安装依赖目录node_modules和package-lock.json文件,重试npm i

请参考:

npm ERR! code ERESOLVEnpm ERR! ERESOLVE could not resolve 报错,版本冲突,最全解决步骤(#^.^#)_npm err! code eresolve npm err! eresolve could not-CSDN博客

1.2.2 镜像过期

安装ffmpeg可能提示镜像证书过期

你使用的镜像地址可能还是这个过期的淘宝镜像:https://registry.npm.taobao.org/

按如下步骤重设镜像地址:

①查看镜像:npm config list

②强制清理镜像缓存:npm cache clean --force

③设置镜像:npm config set registry https://registry.npmmirror.com/(国内推荐淘宝新镜像)

也可:npm config set registry https://registry.npmjs.org/

1.3 把ffmpeg安装到项目里

在项目里的ffmpeg插件目录下找到:

ffmpeg-core.js

ffmpeg-core.wasm

ffmpeg-core-worker.js
复制到项目代码的public目录里

至此,项目里安装ffmpeg完毕。

接下来就是在代码块里使用ffmpeg

2 项目里引用并封装ffmpeg

在util目录下封装ffmpeg.js以便项目全局引用

封装的工具通过:

  1. import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

把ffmpeg插件引入到项目里使用。

完整ffmpeg.js代码:

  1. import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
  2. let ffmpeg = {};
  3. ffmpeg.squeezVideo = async function(file, filename, filetype, width, height, msg) {
  4. console.log('file', file);
  5. console.log('filename', filename);
  6. console.log('filetype', filetype);
  7. console.log('width', width);
  8. console.log('height', height);
  9. // 分辨率
  10. const resolution = `${width}x${height}`;
  11. // 实例化ffmpeg
  12. const ffmpegObj = createFFmpeg({
  13. // ffmpeg路径
  14. corePath: 'ffmpeg-core.js',
  15. // 日志
  16. log: true,
  17. // 进度
  18. progress: ({ ratio }) => {
  19. msg = `完成率: ${(ratio * 100.0).toFixed(1)}%`;
  20. }
  21. })
  22. var { name } = file;
  23. // msg = '正在加载 ffmpeg-core.js'
  24. // 开始加载
  25. await ffmpegObj.load();
  26. // msg = '开始压缩'
  27. // 把文件加到ffmpeg 写文件
  28. ffmpegObj.FS('writeFile', name, await fetchFile(file));
  29. // await ffmpeg.run('-i', name, '-b', '2000000', '-fs', '4194304', '-preset medium', 'superfast', 'output.mp4')
  30. // 开始压缩视频
  31. const compressedFileSize = this.computeFileSize(file);
  32. console.log("After compression,this file size is " + compressedFileSize + " Bytes.");
  33. await ffmpegObj.run('-i', name, '-b', '2000000', '-crf', '18', '-fs', compressedFileSize, '-s', resolution, 'output.mp4');
  34. // msg = '压缩完成'
  35. // 压缩所完成, 读文件 压缩后的文件名称为 output.mp4
  36. const data = ffmpegObj.FS('readFile', 'output.mp4');
  37. // 转换bolb类型
  38. const blob = new Blob([data], { type: 'text/plain;charset=utf-8' });
  39. return new Promise((resolve, reject) => {
  40. const file = new window.File([blob], filename, { type: filetype });
  41. resolve(file);
  42. })
  43. }
  44. ffmpeg.computeFileSize = function(file) {
  45. if(!file){
  46. return '0';
  47. }
  48. if(file.size / 1024 / 1024 > 60){
  49. //30M
  50. return '31457280';
  51. }else if(file.size / 1024 / 1024 <= 60 && file.size / 1024 / 1024 > 30){
  52. return file.size / 2;
  53. }else{
  54. return file.size;
  55. }
  56. }
  57. // 获取上传视频的url
  58. ffmpeg.getObjectURL = function(file) {
  59. let url = null;
  60. window.URL = window.URL || window.webkitURL;
  61. if (window.URL) {
  62. url = window.URL.createObjectURL(file);
  63. } else {
  64. url = URL.createObjectURL(file);
  65. }
  66. return url;
  67. }
  68. // 获取视频的宽高分辨率
  69. ffmpeg.getVideoData = function() {
  70. return new Promise((resolve, reject) => {
  71. const videoElement = document.getElementById('video');
  72. videoElement.addEventListener('loadedmetadata', function () {
  73. resolve({
  74. width: this.videoWidth,
  75. height: this.videoHeight,
  76. duration: this.duration
  77. })
  78. });
  79. })
  80. }
  81. export default ffmpeg;

2.1 ffmpeg压缩参数配置

-b:指定视频比特率

-crf:恒定速率因子,控制输出视频质量的参数。

这个参数的取值范围为0~51,其中0为无损模式。数值越大,画质越差,生成的文件却越小。

从主观上讲,18~28是一个合理的范围。18被认为是视觉无损的(从技术角度上看当然还是有损的),它的输出视频质量和输入视频相当。

-fs:压缩到指定大小,单位Byte

-s:分辨率

控制压缩后视频质量的最重要的是后面三个参数:crf、fs、s

3.视频上传元素

  1. <template>
  2. <el-upload
  3. ref='operationVideoUpload'
  4. :limit="1"
  5. list-type='text'
  6. :class="{disabled:addModelParam.attachments.operationVideo.length>0}"
  7. :action='actionUrl'
  8. :on-success="(res,file)=>handleVideoSuccess(res,file,'operationVideo')"
  9. :before-upload='beforeAvatarUploadVideo'
  10. :on-remove="(file,fileList)=>handleRemove(file,fileList,'operationVideo')"
  11. :auto-upload='true'
  12. :on-exceed="handelFileExceed"
  13. accept='.mp4,.mov,.wmv,.flv,.mvi,.mkv'>
  14. <el-button style="position: relative; margin: -5px"><i class="el-icon-circle-plus-outline" style="color: #66b1ff;">上传附件</i></el-button>
  15. <br/><br/>
  16. <p>{{ msg }}</p>
  17. </el-upload>
  18. <video id="video" hidden controls object-fill="fill"></video>
  19. </template>

如果不想要展示压缩视频,可以去掉video标签。

4.上传压缩脚本

把封装的ffmpeg.js导入到页面使用:

import ffmpeg from "@/utils/ffmpeg";

完整js脚本:

  1. <script>
  2. import ffmpeg from "@/utils/ffmpeg";
  3. export default {
  4. data() {
  5. return {
  6. msg: '',
  7. videoWidth: '',
  8. videoHeight: '',
  9. duration: '',
  10. actionUrl: '',
  11. addModelParam: {
  12. attachments: {
  13. operationVideo: []
  14. }
  15. },
  16. }
  17. },
  18. created() {
  19. this.actionUrl = "你的后端上传文件接口地址URL";
  20. },
  21. methods: {
  22. handleVideoSuccess(res, file, code) {
  23. this.msg = "已完成视频压缩后上传!";
  24. file.url = res.data.url;
  25. file.fileId = res.data.fileId;
  26. this.addModelParam.attachments[code].push(file.fileId);
  27. },
  28. handleAvatarSuccess(res, file, code) {
  29. file.url = res.data.url;
  30. file.fileId = res.data.fileId;
  31. this.addModelParam.attachments[code].push(file.fileId);
  32. },
  33. handleRemove(file, fileList, code) {
  34. this.addModelParam.attachments[code].splice(this.addModelParam.attachments[code].indexOf(file.fileId),1)
  35. },
  36. beforeAvatarUploadVideo(file) {
  37. const isLarge = file.size / 1024 / 1024 > 30;
  38. if (isLarge) {
  39. this.msg = "请稍等,过大的视频正在压缩上传中...";
  40. //压缩视频
  41. return this.uploadCompressVideo(file);
  42. }
  43. },
  44. handelFileExceed(){
  45. this.$message('文件数量超出限制!');
  46. },
  47. // 上传视频文件压缩后再上传
  48. uploadCompressVideo(file) {
  49. if (file) {
  50. let filename = file.name;
  51. let filetype = file.type;
  52. const videoUrl = ffmpeg.getObjectURL(file);
  53. const video = document.getElementById('video');
  54. video.src = videoUrl;
  55. return ffmpeg.getVideoData().then((videoObj) => {
  56. const {width, height} = videoObj;
  57. return ffmpeg.squeezVideo(file, filename, filetype, width, height, this.msg);
  58. })
  59. }
  60. },
  61. },
  62. }
  63. </script>

注意异步处理:异步压缩,再上传

可使用new Promise();

5.其他配置:

5.1 vue项目根目录下的vue.config.js里加配置

  1. headers: {
  2. 'Cross-Origin-Opener-Policy': 'same-origin',
  3. 'Cross-Origin-Embedder-Policy': 'require-corp'
  4. }
  1. module.exports = {
  2. publicPath: './',
  3. devServer: {
  4. client: {
  5. overlay: false,
  6. },
  7. port: 9002,
  8. headers: {
  9. 'Cross-Origin-Opener-Policy': 'same-origin',
  10. 'Cross-Origin-Embedder-Policy': 'require-corp'
  11. }
  12. },
  13. transpileDependencies: []
  14. }

以免出现如下SharedArrayBuffer的报错:

6.其他实现方案

插件video-conversion.js

7.其他视频压缩工具

有时视频过大会导致上传超时,需要将视频压缩小点(不是压缩成zip文件)

在线压缩视频:

迅捷在线压缩视频:视频压缩 - 免费视频压缩软件在线 – 迅捷压缩在线

https://yasuo.xunjiepdf.com/video/

PickFrom在线压缩:在线视频压缩 - 免费在线压缩视频,无论是手机还是电脑, 一键就可以压缩任意视频 - PickFrom

一键压缩:免费在线图片/视频压缩工具 | 视频压缩工具 | 高清无损 | 支持MP4、AVI、FLV视频压缩

(质优)在线视频压缩:https://compress-video-online.com/

https://compress-video-online.com/zh/

(首推)ApowerSoft:免费在线视频压缩工具 - 无水印、无需下载

免费在线视频压缩工具 - 无水印、无需下载

sp简剪:视频压缩工具-在线无损压缩-sp简剪

youcompress:Compress Video, Image, Audio and PDF Files Online | YouCompress

video2Edit:Compress video - make video files smaller online

Media.io:Online Video Compressor - Reduce Large Video Files Size Online

OnlineConvert :Compress Video, reduce video file size - Online Converter

Compress Video, reduce video file size - Online Converter

ClipChamp:https://clipchamp.com/en/utilities-discontinued/

WeCompress :File Compressor ⁠— Compress documents and images online free

Video file converter:Online video converter

File Converter:File Converter - FreeConvert.com

file-converter-online.com:Compress video online for free - file-converter-online.com

标签: vue.js 前端 ffmpeg

本文转载自: https://blog.csdn.net/superit401/article/details/139663775
版权归原作者 ispotu 所有, 如有侵权,请联系我们删除。

“前端Vue使用ffmpeg压缩视频再上传(全网唯一公开真正实现)”的评论:

还没有评论