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

最新的ffmepg.js前端VUE3实现视频、音频裁剪上传功能

package.json

"dependencies": {"@ffmpeg/ffmpeg": "^0.12.10","@ffmpeg/util": "^0.12.1"
}

vue3组件代码

根据需要更改

<script setup lang="ts">
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
import useInject from '@/utils/useInject';import { reactive, onUnmounted } from 'vue';
const { $global, $fn } = useInject();const props: any = defineProps<{params?: any;url?: any;
}>();let ffmpegObj: any = reactive({file: null,urlpre: null,url: null,params: {...(props?.params || {}),ext: '',starttime: 0,endtime: 3,maxtime: 0,},
});const ffmpeg = new FFmpeg();function filechange(e: any) {ffmpegObj.file = e.target.files[0];// 原视频预览方案一const reader: any = new FileReader();reader.readAsDataURL(ffmpegObj.file);reader.onload = () => {ffmpegObj.url = '';ffmpegObj.urlpre = reader.result;const audioElement: any = new Audio(ffmpegObj.urlpre);audioElement.addEventListener('loadedmetadata', () => {ffmpegObj.params.maxtime = audioElement.duration;ffmpegObj.params.starttime = 0;ffmpegObj.params.endtime = audioElement.duration;});};// 原视频预览方案二// const reader: any = new FileReader();// reader.readAsArrayBuffer(ffmpegObj.file);// let blob = null;// reader.onload = (e: any) => {//     if (typeof e.target.result === 'object') {//         blob = new Blob([e.target.result]);//     } else {//         blob = e.target.result;//     }//     ffmpegObj.url = '';//     if (blob == null) return;//     const url = URL.createObjectURL(blob);//     ffmpegObj.urlpre = url;//     const audioElement = new Audio(url);//     audioElement.addEventListener('loadedmetadata', function () {//         ffmpegObj.params.maxtime = audioElement.duration;//         ffmpegObj.params.starttime = 0;//         ffmpegObj.params.endtime = audioElement.duration;//     });// };
}
async function doffmpeg() {try {if (!ffmpegObj.file) {return;}ffmpegObj.fileext = ffmpegObj.file.name.split('.').pop();const inputName = `input.${ffmpegObj.fileext}`;const outputName = `output.${ffmpegObj.params.ext ? ffmpegObj.params.ext : ffmpegObj.fileext}`;console.log(666.001, ffmpeg, ffmpegObj);ffmpeg.on('log', ({ message: msg }) => {ffmpegObj.msglogger = msg;});await ffmpeg.load({coreURL: await toBlobURL('./ffmpeg/ffmpeg-core.js','text/javascript'),wasmURL: await toBlobURL('./ffmpeg/ffmpeg-core.wasm','application/wasm'),workerURL: await toBlobURL(`./ffmpeg/ffmpeg-core.worker.js`,'text/javascript'),});await ffmpeg.writeFile(inputName, await fetchFile(ffmpegObj.urlpre));await ffmpeg.exec(['-ss',`${ffmpegObj.params.starttime !== undefined? ffmpegObj.params.starttime: 0}`,'-t',`${(ffmpegObj.params.endtime !== undefined? ffmpegObj.params.endtime: 3) -(ffmpegObj.params.starttime !== undefined? ffmpegObj.params.starttime: 0)}`,'-i',inputName,outputName,]);ffmpegObj.data = await ffmpeg.readFile(outputName);ffmpegObj.blob = new Blob([ffmpegObj.data.buffer], {type:'video/' + ffmpegObj.params.ext? ffmpegObj.params.ext: ffmpegObj.fileext,});ffmpegObj.url = URL.createObjectURL(ffmpegObj.blob);ffmpegObj.urlpre = ''; // 清空原预览视频} catch (err) {alert('出错了');throw err;}
}
function blobToBase64(blob: any) {console.log(666.3002, blob);return new Promise((resolve, reject) => {const fileReader = new FileReader();fileReader.readAsDataURL(blob);fileReader.onload = () => {resolve(fileReader.result);};fileReader.onerror = () => {reject(new Error('文件流异常'));};});
}
// function convertBlobToFile(blob, fileName) {
//     blob.lastModifiedDate = new Date();
//     blob.name = fileName;
//     return blob;
// }
async function submit() {await doffmpeg();const resdata: any = await blobToBase64(ffmpegObj.blob);// const resdata: any = convertBlobToFile(ffmpegObj.blob, 'aaa');console.log(666.30002, resdata);$fn.useApiFiles().request({data: props.url? { url: props.url }: {dir: 'chat/chat',uid: $fn.As.Uuid('CU'),ext:'.' +(ffmpegObj.params.ext? ffmpegObj.params.ext: ffmpegObj.fileext),data: resdata,},}).then((res: any) => {console.log(666.789, res);props?.params?.fn(res);}).catch((err: any) => {$global.tipsfn({ type: 'err', con: err });});
}//下载
function downffmpeg() {const oA: any = document.createElement('a');oA.download ='video_' +Date.now() +'.' +(ffmpegObj.params.ext ? ffmpegObj.params.ext : ffmpegObj.fileext);oA.href = ffmpegObj.url;document.body.appendChild(oA);oA.click();// 释放 URL 对象URL.revokeObjectURL(oA.href);oA.remove();
}
onUnmounted(() => {ffmpegObj = null;
});
</script>
<template><div class="as-ff-area"><div class="as-show-area"><!-- <template v-if="ffmpegObj.urlpre"> -->原视频<video :src="ffmpegObj.urlpre" controls></video><!-- </template> --><!-- <template v-else> -->裁剪后视频<video :src="ffmpegObj.url" controls></video><!-- </template> -->日志:{{ ffmpegObj.params.starttime }}-{{ ffmpegObj.params.endtime }}({{ ffmpegObj.params.maxtime }})<inputtype="range"v-model="ffmpegObj.params.starttime"min="0":max="ffmpegObj.params.maxtime"/><inputtype="range"v-model="ffmpegObj.params.endtime"min="0":max="ffmpegObj.params.maxtime"/><!-- <input type="number" v-model="ffmpegObj.params.starttime" /><input type="number" v-model="ffmpegObj.params.endtime" /> -->{{ ffmpegObj.msglogger }}{{ ffmpegObj.msgprogress }}</div><div class="as-file-area">选择图片:<input class="file" type="file" @change="filechange" /></div><div class="as-btn-area"><button @click="doffmpeg()">裁剪</button><button @click="downffmpeg()">下载</button><button @click="submit()">提交</button></div></div>
</template><style scoped>
.as-ff-area {width: 100%;height: 100%;display: flex;flex-direction: column;
}
.as-btn-area {text-align: center;height: auto;
}
.as-btn-area > button {user-select: none;padding: 5px 12px;margin: 15px 5px 0 5px;
}
.as-file-area {padding: 5px 12px;text-align: center;height: auto;width: auto;display: inline-block;background-color: var(--ch1);
}
.as-show-area {flex-grow: 1;width: 100%;overflow: auto;display: flex;justify-content: center;align-items: center;flex-direction: column;
}
</style>

相关文章:

  • FileZilla:不安全的服务器,不支持 FTP over TLS 原因与解决方法
  • 浅谈一下实例化
  • C++期末复习
  • nvm,node不是内部命令,npm版本不支持问题(曾经安装过nodejs)
  • Python报错:AttributeError: <unknown>.DeliveryStore 获取Outlook邮箱时报错
  • MySQL 高级 - 第十一章 | 索引优化与查询优化
  • 力扣 74.搜索二维矩阵
  • vue 将图片url转base64
  • 优化财务管理制度提升企业经营效益—以审计代理记账为例
  • JWT及单点登录实现
  • window.setInterval(func,interval)定时器
  • Java | Leetcode Java题解之第137题只出现一次的数字II
  • 高质量 HarmonyOS 权限管控流程
  • 尝试使用blazor(二)Blazor WebAssembly(WASM)与Server之间有什么区别?
  • Python | 洗盘子(栈)
  • .pyc 想到的一些问题
  • @jsonView过滤属性
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • bootstrap创建登录注册页面
  • DataBase in Android
  • DOM的那些事
  • HashMap ConcurrentHashMap
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java 23种设计模式 之单例模式 7种实现方式
  • Javascript Math对象和Date对象常用方法详解
  • Java的Interrupt与线程中断
  • Laravel 中的一个后期静态绑定
  • learning koa2.x
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • Otto开发初探——微服务依赖管理新利器
  • rc-form之最单纯情况
  • react-native 安卓真机环境搭建
  • supervisor 永不挂掉的进程 安装以及使用
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • yii2中session跨域名的问题
  • 大型网站性能监测、分析与优化常见问题QA
  • 给新手的新浪微博 SDK 集成教程【一】
  • 关于extract.autodesk.io的一些说明
  • 关于Flux,Vuex,Redux的思考
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 如何优雅地使用 Sublime Text
  • 深入浅出Node.js
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 用Python写一份独特的元宵节祝福
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 【干货分享】dos命令大全
  • Java总结 - String - 这篇请使劲喷我
  • Python 之网络式编程
  • ​渐进式Web应用PWA的未来
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (23)mysql中mysqldump备份数据库
  • (35)远程识别(又称无人机识别)(二)
  • (js)循环条件满足时终止循环
  • (k8s)Kubernetes 从0到1容器编排之旅