下載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
// 實例化ffmpeg
const 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.mp4
const data = ffmpeg.FS('readFile', 'put.mp4')
?名詞解釋:-b: 比特率(也就是速度大?。?-crf: 壓縮的視頻質量?? -fs:? 把視頻壓縮到指定大?。ㄓ锌赡軙嚎s到指定大小,但是可能會剪切指定大小以后的視頻片段并刪除超出的部分)? -preset medium:? 壓縮速度? ? -s: 分辨率? (可以用于指定視頻的分辨率? 分辨率越大 壓縮時間越慢? ?越小 時間越快)? ? ?put.mp4:壓縮完成后的文件名稱
- 壓縮完的視頻格式是blob格式按照需要可以將視頻格式轉換成file格式,代碼如下:
// 類型轉換 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)
})
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
})
})
})
},
拿到視頻的寬高,壓縮的時候可以等比縮放一下
這里有個坑值得注意一下:如果頁面上沒有加載出來視頻的話,就不會觸發(fā)得到視頻寬高的,需要先把視頻加載出來才行? 代碼如下:
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.js
import { 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 轉換 file
const 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不能用于微信環(huán)境或者是企微環(huán)境,代碼執(zhí)行不下去。
效果視頻
ffmpeg壓縮視頻
如果各位視頻看不到的話,請移步到我的主頁進行觀看
?還有一種插件好像可以? video-conversion.js? 但是沒有找到官網,有小伙伴研究成功的話,踢我一下哈文章來源:http://www.zghlxwxcb.cn/news/detail-760650.html
文章若有不足之處? 煩請指正文章來源地址http://www.zghlxwxcb.cn/news/detail-760650.html
到了這里,關于前端ffmpeg壓縮視頻的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!