前端ffmpeg压缩视频
时间:2024-04-17 09:10:28 来源:网络cs 作者:胡椒 栏目:国内电商 阅读:
下载ffmpeg
npm install @ffmpeg/core @ffmpeg/ffmpeg
这里需要注意两个插件的版本 "@ffmpeg/core": "^0.10.0", "@ffmpeg/ffmpeg": "^0.10.1"
配置ffmpeg
安装好插件以后,需要配置一下代码,否则会报错:
1、以VUE为例 在vue.config.js文件中配置请求头
devServer: {headers: {'Cross-Origin-Opener-Policy': 'same-origin','Cross-Origin-Embedder-Policy': 'require-corp'}}
2、在页面中实例化ffmpeg的时候可能会报找不到模块儿的错误
const ffmpeg = createFFmpeg({ // ffmpeg路径 corePath: 'ffmpeg-core.js', // 日志 log: true, // 进度 progress: ({ ratio }) => { _this.msg = `完成率: ${(ratio * 100.0).toFixed(1)}%` }})
因此,最好将下载好的插件文件放到public文件夹里面就可以了
引入ffmpeg使用ffmpeg压缩视频
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
文件上传 获取上传的文件 <input id="upload" type="file" accept="video/mp4" capture="camcorder" @change="upload">
注:capture="camcorder" 代表获取手机的摄像头录像 自行查看
实例化ffmpeg// 实例化ffmpegconst ffmpeg = createFFmpeg({ // ffmpeg路径 corePath: 'ffmpeg-core.js', // 日志 log: true, // 进度 progress: ({ ratio }) => { _this.msg = `完成率: ${(ratio * 100.0).toFixed(1)}%` }})
压缩视频 await ffmpeg.load()this.msg = '开始压缩'// 把文件加到ffmpeg 写文件ffmpeg.FS('writeFile', name, await fetchFile(file))// await ffmpeg.run('-i', name, '-b', '2000000', '-fs', '4194304', '-preset medium', 'superfast', 'put.mp4')// 开始压缩视频await ffmpeg.run('-i', name, '-b', '2000000', '-crf', '23', '-fs', '4194304', '-s', resolution, 'put.mp4')this.msg = '压缩完成'// 压缩所完成, 读文件 压缩后的文件名称为 put.mp4const data = ffmpeg.FS('readFile', 'put.mp4')
名词解释:-b: 比特率(也就是速度大小) -crf: 压缩的视频质量 -fs: 把视频压缩到指定大小(有可能会压缩到指定大小,但是可能会剪切指定大小以后的视频片段并删除超出的部分) -preset medium: 压缩速度 -s: 分辨率 (可以用于指定视频的分辨率 分辨率越大 压缩时间越慢 越小 时间越快) put.mp4:压缩完成后的文件名称
压缩完的视频格式是blob格式按照需要可以将视频格式转换成file格式,代码如下:// 类型转换 blob 转换 filetransToFile (data) { console.log(data) const _this = this var file = [] // 转换bolb类型 const blob = new Blob([data], { type: 'text/plain;charset=utf-8' }) // 这么写是因为文件转换是异步任务 const transToFile = async (blob, fileName, fileType) => { return new window.File([blob], fileName, { type: fileType }) } const textContain = transToFile(blob, 'put.mp4', 'video/mp4') // 转换完成后可以将file对象传给接口 textContain.then((res) => { file.push(res) console.log('res', res) }) return file},
如果你嫌压缩的时间太长了,可以控制视频的分辨率 代码如下: getVideoData () { return new Promise((resolve, reject) => { const videoElement = document.getElementById('video') videoElement.addEventListener('loadedmetadata', function () { resolve({ width: this.videoWidth, height: this.videoHeight, duration: this.duration }) }) })},
拿到视频的宽高,压缩的时候可以等比缩放一下
这里有个坑值得注意一下:如果页面上没有加载出来视频的话,就不会触发得到视频宽高的,需要先把视频加载出来才行 代码如下:
getObjectURL (file) { let url = null window.URL = window.URL || window.webkitURL if (window.URL) { url = window.URL.createObjectURL(file) } else { url = URL.createObjectURL(file) } return url}
献上所有代码
<template> <div class="video-box"> <video id="video" controls object-fill="fill"></video><br /> <input id="upload" type="file" accept="video/mp4" capture="camcorder" @change="upload"> </div></template><script>import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'export default { data () { return { msg: '', videoWidth: '', videoHeight: '', duration: '' } }, methods: { // 选择文件 async upload (e) { console.log('start', e) console.log('start', e.target.files[0]) var _this = this if (e.target.files[0]) { var filename = e.target.files[0].name var filetype = e.target.files[0].type const videoUrl = _this.getObjectURL(e.target.files[0]) const video = document.getElementById('video') video.src = videoUrl this.getVideoData().then((videoObj) => { const file = e.target.files[0] console.log('videoObj:', videoObj) const { width, height } = videoObj const result = _this.squeezVideo(file, filename, filetype, width, height, _this.msg) result.then(res => { console.log('resultFile', res) }) }) } }, // 压缩视频 async squeezVideo (file, filename, filetype, width, height) { console.log('squeezingVideo file name: ', file.name) console.log('squeezingVideo file type: ', file.type) console.log('squeezingVideo file path: ', file.path) console.log('squeezingVideo file size: ', file.size) console.log('squeezingVideo file lastModified: ', file.lastModified) console.log('squeezingVideo file lastModifiedDate: ', file.lastModifiedDate) const _this = this // 分辨率 const resolution = `${width / 2}x${height / 2}` // 实例化ffmpeg const ffmpeg = createFFmpeg({ // ffmpeg路径 corePath: 'ffmpeg-core.js', // 日志 log: true, // 进度 progress: ({ ratio }) => { _this.msg = `完成率: ${(ratio * 100.0).toFixed(1)}%` } }) var { name } = file this.msg = '正在加载 ffmpeg-core.js' // 开始加载 await ffmpeg.load() this.msg = '开始压缩' // 把文件加到ffmpeg 写文件 ffmpeg.FS('writeFile', name, await fetchFile(file)) // await ffmpeg.run('-i', name, '-b', '2000000', '-fs', '4194304', '-preset medium', 'superfast', 'put.mp4') // 开始压缩视频 await ffmpeg.run('-i', name, '-b', '2000000', '-crf', '23', '-fs', '4194304', '-s', resolution, 'put.mp4') this.msg = '压缩完成' // 压缩所完成, 读文件 压缩后的文件名称为 put.mp4 const data = ffmpeg.FS('readFile', 'put.mp4') // 转换压缩后的视频格式 当前为 blob 格式 var filed = _this.transToFile(data) console.log('transToFile: ', filed) return new Promise((resolve, reject) => { if (filed) { resolve({ squzingFile: filed }) } }) }, // 获取视频的宽高分辨率 getVideoData () { return new Promise((resolve, reject) => { const videoElement = document.getElementById('video') videoElement.addEventListener('loadedmetadata', function () { resolve({ width: this.videoWidth, height: this.videoHeight, duration: this.duration }) }) }) }, // 获取上传视频的url getObjectURL (file) { let url = null window.URL = window.URL || window.webkitURL if (window.URL) { url = window.URL.createObjectURL(file) } else { url = URL.createObjectURL(file) } return url }, // 类型转换 blob 转换 file transToFile (data) { console.log(data) const _this = this var file = [] // 转换bolb类型 const blob = new Blob([data], { type: 'text/plain;charset=utf-8' }) // 这么写是因为文件转换是异步任务 const transToFile = async (blob, fileName, fileType) => { return new window.File([blob], fileName, { type: fileType }) } const textContain = transToFile(blob, 'put.mp4', 'video/mp4') // 转换完成后可以将file对象传给接口 textContain.then((res) => { file.push(res) console.log('res', res) // _this.confirm(file) }) return file } }}</script>
可以封装压缩视频代码
目录src/utils/ffmpeg.jsimport { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'// 压缩视频const squeezVideo = async (file, filename, filetype, width, height) => { console.log('file', file) console.log('filename', filename) console.log('filetype', filetype) console.log('width', width) console.log('height', height) // 分辨率 const resolution = `${width / 2}x${height / 2}` // 实例化ffmpeg const ffmpeg = createFFmpeg({ // ffmpeg路径 corePath: 'ffmpeg-core.js', // 日志 log: true // 进度 // progress: ({ ratio }) => { // msg = `完成率: ${(ratio * 100.0).toFixed(1)}%` // } }) console.log('file---', file) 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', 'put.mp4') // 开始压缩视频 await ffmpeg.run('-i', name, '-b', '2000000', '-crf', '23', '-fs', '4194304', '-s', resolution, 'put.mp4') // msg = '压缩完成' // 压缩所完成, 读文件 压缩后的文件名称为 put.mp4 const data = ffmpeg.FS('readFile', 'put.mp4') // 转换压缩后的视频格式 当前为 blob 格式 var res = transToFile(data, filename, filetype) return new Promise((result, reject) => { result({ filed: res }) })}// 类型转换 blob 转换 fileconst transToFile = (data, filename, filetype) => { var filed = [] console.log(data) // 转换bolb类型 const blob = new Blob([data], { type: 'text/plain;charset=utf-8' }) // 这么写是因为文件转换是异步任务 const transToFile = async (blob, fileName, fileType) => { return new window.File([blob], fileName, { type: fileType }) } const textContain = transToFile(blob, filename, filetype) // 转换完成后可以将file对象传给接口 textContain.then((res) => { filed.push(res) console.log('res', res) }) return filed}export { squeezVideo }
注意事项:
ffmpeg是一款很强大的视频编辑工具,你可以自己研究研究,上述的代码可以自己封装一下,另外ffmpeg不能用于微信环境或者是企微环境,代码执行不下去。
效果视频
ffmpeg压缩视频
如果各位视频看不到的话,请移步到我的主页进行观看
还有一种插件好像可以 video-conversion.js 但是没有找到官网,有小伙伴研究成功的话,踢我一下哈
文章若有不足之处 烦请指正
阅读本书更多章节>>>>本文链接:https://www.kjpai.cn/guonei/2024-04-17/159680.html,文章来源:网络cs,作者:胡椒,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!
上一篇:【已解决】解决前端模块与Node.js版本不兼容问题
下一篇:返回列表