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 }})
- <input
- type="range"
- v-model="ffmpegObj.params.starttime"
- min="0"
- :max="ffmpegObj.params.maxtime"
- />
- <input
- type="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>
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |