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

video素材格式转换--mp4转webm(vue3+Nodejs)

总体实现使用ffmpeg


自动化demo实现 vue3+Nodejs+ffmpeg

一、官网下载ffmpeg

https://ffmpeg.org/

1-1选择对应系统下载

1-2下载完成后配置环境变量

1-2-1将下载文件的bin目录配置到环境变量中

例如:D:\ffmpeg\bin

1-3测试ffmpeg是否安装成功

ffmpeg -version

如图 证明安装成功!!!!

二、手动使用命令转video格式

cmd 打开视频所在目录 

等待完成即可!

三、自动化demo

工作中 有比较大的素材量 可直接上传文件等待转type即可 完成后下载视频

代码示例:

3-1 vue3

<template>
  <div>
    <a-upload
      name="file"
      action="http://localhost:3000/uploadWebm"
      @change="handleChange"
    >
      <a-button>
        <upload-outlined></upload-outlined>
        请上传视频
      </a-button>
    </a-upload>
    <video :src="url" controls v-if="url"></video>
  </div>
</template>
<script setup>
import { ref } from "vue";
import { message } from "ant-design-vue";
import { UploadOutlined } from "@ant-design/icons-vue";

const url = ref("");
const checkTaskInterval = ref(null); // 将定时器ID存储在响应式引用中

const checkTaskStatus = async () => {
  try {
    const response = await fetch("http://localhost:3000/status", {
      method: "GET",
    });
    if (response.ok) {
      const data = await response.json();
      console.log(data.event, "data.event");
      if (data.event === "end") {
        console.log("endend");
        clearInterval(checkTaskInterval.value); // 使用响应式引用的值来清除定时器
        checkTaskInterval.value = null; // 将响应式引用的值设置为null
        url.value = data.data.url;
      } else if (data.event === "error") {
        clearInterval(checkTaskInterval.value);
        checkTaskInterval.value = null;
        message.error("上传失败:" + data.data);
      }
    }
  } catch (error) {
    message.error("上传失败");
    console.error("上传失败:", error);
    clearInterval(checkTaskInterval.value);
    checkTaskInterval.value = null;
  }
};

const handleChange = async (info) => {
  console.log(info);
  // 清除之前的定时器(如果有)
  if (checkTaskInterval.value) {
    clearInterval(checkTaskInterval.value);
  }
  checkTaskInterval.value = setInterval(() => {
    checkTaskStatus();
  }, 3000);
};
</script>
<style lang="less" scoped>
</style>

3-2 Nodejs

3-2-1安装 fluent-ffmpeg

npm install fluent-ffmpeg --save

3-2-2 完整代码示例 

var express = require('express');
var router = express.Router();
var multiparty = require('multiparty');
const multer = require('multer')
const upload = multer({ dest: 'upload/' })
const { execFile } = require('child_process');
const path = require('path');
const fs = require('fs');
const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = path.join('d:', 'ffmpeg', 'bin', 'ffmpeg.exe');//ffmpeg.exe的路径
const iconv = require('iconv-lite'); // 用于处理中文路径
ffmpeg.setFfmpegPath(ffmpegPath);

//video转webm
router.post('/uploadWebm', upload.single('file'), (req, res) => {
  const file = req.file;
  const srcPath = file.path;
  console.log(file.originalname, "file.originalname");

  const originalNameBuffer = Buffer.from(file.originalname, 'binary');
  const utf8Name = iconv.decode(originalNameBuffer, 'UTF-8'); // 将文件名从二进制转换为 UTF-8 编码
  const dstPath = path.join('upload', `${path.basename(utf8Name, path.extname(utf8Name))}.webm`);
  console.log(dstPath, "dstPath");
  // 初始化状态信息
  statusInfo = {
    event: "start",
    data: `Started processing ${file.originalname}`,
    finished: false
  };

  ffmpeg(srcPath)
  .on('start', (commandLine) => {
    statusInfo.event = "start";
    statusInfo.data = commandLine;
  })
  .on('progress', (progress) => {
    statusInfo.event = "progress";
    statusInfo.data = progress;
  })
  .on('error', (err) => {
    statusInfo.event = "error";
    statusInfo.data = err;
    statusInfo.finished = true;
    res.status(500).send({ code: 500, event: "error", data: err });
    fs.unlinkSync(srcPath);
  })
  .on('end', () => {
    statusInfo.event = "end";
    statusInfo.data = {message: "Processing finished", url: `http://localhost:3000/upload/${path.basename(dstPath)}`};
    statusInfo.finished = true;
    fs.unlinkSync(srcPath);
  })
  .addOption('-c:v libvpx-vp9')
  .addOption('-c:a libopus')
  .addOption('-b:v 1M')
  .addOption('-b:a 128k')
  .toFormat('webm')
  .save(dstPath);
});

// 客户端轮询的接口
router.get('/status', (req, res) => {
  const filename = req.params.filename;
  if (statusInfo && !statusInfo.finished) {
    res.send({ code: 200, event: statusInfo.event, data: statusInfo.data });
  } else if (statusInfo) {
    res.send({ code: 200, event: statusInfo.event, data: statusInfo.data });
  } else {
    res.status(404).send({ code: 404, message: "File not found" });
  }
});



http://www.kler.cn/a/387748.html

相关文章:

  • 出海攻略,如何一键保存Facebook视频素材
  • WPF中的ResizeMode
  • Flink API 的层次结构
  • 力扣 653. 两数之和 IV 二叉树/binary-tree two-sum IV
  • 深度学习-图像评分实验(TensorFlow框架运用、读取处理图片、模型建构)
  • 前端代码分析题(选择题、分析题)——this指向、原型链分析
  • 如何运营Github Org
  • Hunyuan-Large:推动AI技术进步的下一代语言模型
  • 刘艳兵-DBA027-在Oracle数据库,通常可以使用如下方法来得到目标SQL的执行计划,那么通过下列哪些方法得到的执行计划有可能是不准确的?
  • 鸿蒙next版开发:ArkTS组件自定义事件拦截详解
  • 腾讯混元3D模型Hunyuan3D-1.0部署与推理优化指南
  • 【PGCCC】Postgresql LWLock 原理
  • 孤岛的总面积(Dfs C#
  • IP系列之scan讨论
  • Java学习篇之JVM 调优
  • Hive 的数据类型
  • 分布式中常见的问题及其解决办法
  • BUG: scheduling while atomic
  • 软考中级 软件设计师 上午考试内容笔记(个人向)Part.2
  • 道品科技智慧农业中的自动气象检测站
  • vue3+ts+element-ui实现的可编辑table表格组件 插入单行多行 组件代码可直接使用
  • 当AI遇上时尚:未来的衣橱会由机器人来打理吗?
  • 133.鸿蒙基础01
  • 在IntelliJ IDEA中创建带子模块的SpringBoot工程
  • Spring Boot 与 Vue 共筑高校网上订餐卓越平台
  • js实现各种经典排序算法