当前位置: 首页 > news >正文

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运行命令:

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

如果出现安装问题:

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

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插件目录下找到: 
复制到项目代码的public目录里

1.3.1 ffmpeg压缩参数配置

-b:指定视频比特率

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

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

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

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

-s:分辨率

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

1.4 项目里引用并封装ffmpeg

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

封装的工具通过:

import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'

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

完整ffmpeg.js代码:

import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
let ffmpeg = {};ffmpeg.squeezVideo = async function(file, filename, filetype, width, height, msg) {console.log('file', file)console.log('filename', filename)console.log('filetype', filetype)console.log('width', width)console.log('height', height)// 分辨率const resolution = `${width}x${height}`// 实例化ffmpegconst ffmpeg = createFFmpeg({// ffmpeg路径corePath: 'ffmpeg-core.js',// 日志log: true,// 进度progress: ({ ratio }) => {msg = `完成率: ${(ratio * 100.0).toFixed(1)}%`}})var { name } = file// msg = '正在加载 ffmpeg-core.js'// 开始加载await ffmpeg.load()// msg = '开始压缩'// 把文件加到ffmpeg   写文件ffmpeg.FS('writeFile', name, await fetchFile(file))// await ffmpeg.run('-i', name, '-b', '2000000', '-fs', '4194304', '-preset medium', 'superfast', 'output.mp4')// 开始压缩视频await ffmpeg.run('-i', name, '-b', '2000000', '-crf', '18', '-fs', '31457280', '-s', resolution, 'output.mp4')// msg = '压缩完成'// 压缩所完成,   读文件  压缩后的文件名称为 output.mp4const data = ffmpeg.FS('readFile', 'output.mp4')// 转换bolb类型const blob = new Blob([data], { type: 'text/plain;charset=utf-8' })return new Promise((resolve, reject) => {const file = new window.File([blob], filename, { type: filetype })resolve(file)})
}// 获取上传视频的url
ffmpeg.getObjectURL = function(file) {let url = nullwindow.URL = window.URL || window.webkitURLif (window.URL) {url = window.URL.createObjectURL(file)} else {url = URL.createObjectURL(file)}return url
}// 获取视频的宽高分辨率
ffmpeg.getVideoData = function() {return new Promise((resolve, reject) => {const videoElement = document.getElementById('video')videoElement.addEventListener('loadedmetadata', function () {resolve({width: this.videoWidth,height: this.videoHeight,duration: this.duration})})})
}export default ffmpeg

2.视频上传元素

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

3.上传压缩脚本

<script>
import ffmpeg from "@/utils/ffmpeg";export default {data() {return {msg: '',videoWidth: '',videoHeight: '',duration: '',actionUrl: ''}},created() {this.actionUrl = "你的后端上传文件接口地址URL";},methods: {handleVideoSuccess(res, file, code) {this.msg = "已完成视频压缩后上传!";file.url = res.data.url;file.fileId = res.data.fileId;this.addModelParam.attachments[code].push(file.fileId);},handleAvatarSuccess(res, file, code) {file.url = res.data.url;file.fileId = res.data.fileId;this.addModelParam.attachments[code].push(file.fileId);},handleRemove(file, fileList, code) {this.addModelParam.attachments[code].splice(this.addModelParam.attachments[code].indexOf(file.fileId),1)},beforeAvatarUploadVideo(file) {const isLarge = file.size / 1024 / 1024 > 30;if (isLarge) {this.msg = "请稍等,过大的视频正在压缩上传中...";//压缩视频return this.uploadCompressVideo(file);}},handelFileExceed(){this.$message('文件数量超出限制!');},// 上传视频文件压缩后再上传uploadCompressVideo(file) {if (file) {let filename = file.name;let filetype = file.type;const videoUrl = ffmpeg.getObjectURL(file)const video = document.getElementById('video')video.src = videoUrl;return ffmpeg.getVideoData().then((videoObj) => {const {width, height} = videoObj;return ffmpeg.squeezVideo(file, filename, filetype, width, height, this.msg);})}},
},}
</script>

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

可使用Promise

4.其他配置:

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

headers: {'Cross-Origin-Opener-Policy': 'same-origin','Cross-Origin-Embedder-Policy': 'require-corp'
}
module.exports = {publicPath: './',devServer: {client: {overlay: false,},port: 9002,headers: {'Cross-Origin-Opener-Policy': 'same-origin','Cross-Origin-Embedder-Policy': 'require-corp'}},transpileDependencies: []}

以免出现如下SharedArrayBuffer的报错:

5.其他实现方案

插件video-conversion.js

http://www.lryc.cn/news/371462.html

相关文章:

  • 样式的双向绑定的2种方式,实现样式交互效果
  • 供应链经理面试题
  • 快速理解 Node.js 版本差异:3 分钟指南
  • 【Qt实现录频】
  • Golang编译导致的代码错觉
  • SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件
  • web前端文本大小:从入门到精通的全方位解析
  • 【报文数据流中的反压处理】
  • 数据挖掘丨轻松应用RapidMiner机器学习内置数据分析案例模板详解(下篇)
  • 时代巨兽!深度神经网络如何改变我们的世界?
  • LVS+Keepalived高可用负载均衡群集
  • 【MySQL】MySQL45讲-读书笔记
  • python:faces swap
  • Android开发之音乐播放器添加排行需求
  • latex 方括号编号
  • Vue CLI 4与项目构建实战指南
  • 深入解析Web通信 HTTP、HTTPS 和 WebSocket
  • FISCO BCOS x GitLink,为国产开源技术生态注入新活力
  • Linux crontabs定时执行任务
  • QNX简述
  • [Llama3] ReAct Prompt 测试实验
  • nodejs 某音douyin网页端搜索接口及x_bogus、a_bogus(包含完整源码)(2024-06-13)
  • 继承深度剖析
  • 使用 Vue 和 Ant Design 实现抽屉效果的模块折叠功能
  • Springboot整合SpringCache+redis简化缓存开发
  • 关于EOF标识符
  • 家用洗地机排行榜前十名:2024十大王牌机型精准种草
  • 【Chrome插件】如何在Chrome插件开发中处理复杂数据结构的存储
  • MySQL 保姆级教程(二):使用 MySQL 检索数据
  • Sui Bridge在测试网上线并推出10万SUI激励计划