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

FFmpeg的简单使用【Windows】--- 视频倒叙播放

实现功能

点击【选择文件】按钮可以选择视频,当点击【开始处理】按钮之后,会先将视频上传到服务器,然后开始进行视频倒叙播放的处理,当视频处理完毕之后会将输出的文件路径返回,同时在页面中将处理好的视频展示出来。

效果展示

转换成功效果展示
上传成功
处理后

代码实现

说明:

前端代码是使用vue编写的。

后端接口的代码是使用nodejs进行编写的。

前端代码

<template><div id="app"><!-- 显示上传的视频 --><div><h2>将要处理的视频</h2><videov-for="video in uploadedVideos":key="video.src":src="video.src"controlsstyle="width: 200px"></video></div><!-- 上传视频按钮 --><input type="file" @change="uploadVideo" accept="video/*" /><!-- 显示处理后的视频 --><div><h2>已处理后的视频</h2><videov-for="video in processedVideos":key="video.src":src="video.src"controlsstyle="width: 200px"></video></div><button @click="processVideos">开始处理</button></div>
</template><script setup>
import axios from "axios";
import { ref } from "vue";const uploadedVideos = ref([]);
const processedVideos = ref([]);
let videoIndex = 0;const uploadVideo = async (e) => {const files = e.target.files;for (let i = 0; i < files.length; i++) {const file = files[i];const videoSrc = URL.createObjectURL(file);uploadedVideos.value.push({ id: videoIndex++, src: videoSrc, file });}
};const processVideos = async () => {const formData = new FormData();for (const video of uploadedVideos.value) {formData.append("video", video.file); // 使用实际的文件对象}try {const response = await axios.post("http://localhost:3000/user/single/process",formData,{headers: {"Content-Type": "multipart/form-data",},});const processedVideoSrc = response.data.path;processedVideos.value.push({id: videoIndex++,src: "http://localhost:3000/" + processedVideoSrc,});} catch (error) {console.error("Error processing video:", error);}
};
</script>

补充说明:

 accept="video/*":指定了只接受视频文件类型,这将过滤掉非视频文件,使得用户在选择文件时只能看到并选择视频文件。

video/*:是一个通配符,表示所有已知的视频文件类型。如果你只想接受特定的视频格式(例如MP4和WebM),你可以指定他们,如下所示:

accept=".mp4, .webm"

或者,如果你想要更精确地控制,可以使用MIME类型:

accept="video/mp4, video/webm"

后端代码

routers =》users.js

var express = require('express');
var router = express.Router();
const multer = require('multer');
const ffmpeg = require('fluent-ffmpeg');
const path = require('path');
const upload = multer({dest: 'public/uploads/',storage: multer.diskStorage({destination: function (req, file, cb) {cb(null, 'public/uploads'); // 文件保存的目录},filename: function (req, file, cb) {// 提取原始文件的扩展名const ext = path.extname(file.originalname).toLowerCase(); // 获取文件扩展名,并转换为小写// 生成唯一文件名,并加上扩展名const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);const fileName = uniqueSuffix + ext; // 新文件名cb(null, fileName); // 文件名}})
});
const fs = require('fs');// 处理单个视频文件
router.post('/single/process', upload.single('video'), (req, res) => {console.log(req.file)const videoPath = req.file.path;// 使用filename进行拼接是为了防止视频被覆盖const outputPath = `public/processed/reversed_${req.file.filename}`;ffmpeg().input(videoPath).outputOptions(['-vf reverse'// 反转视频帧顺序]).output(outputPath).on('end', () => {res.json({ message: 'Video processed successfully.', path: outputPath.replace('public', '') });}).on('error', (err) => {console.log(err)res.status(500).json({ error: 'An error occurred while processing the video.' });}).run();
});module.exports = router;

multer配置项说明:

  • 配置选项:
    • dest:指定了文件的临时存储路径,如果提供了storage选择,则dest可能不会被使用。
    • storage:使用multer.diskStorage() 来定义文件如何存储在磁盘上。
  • destination函数:
    • 这个函数用于指定文件存储的目录
    • req:请求对象
    • file:包含了关于上传文件的信息
    • cb:回调函数,用于通知multer存储路径
  • filename函数:
    • 这个函数用于生成存储在磁盘上的文件名
    • req:请求对象
    • file:含有文件的相关信息
    • cb:回调函数,用于通知穆拉特人文件名
    • 在这里,我们生成了一个唯一的文件名,该文件名包含当前时间戳和一个随机数,以避免文件名冲突,并保留了原始文件的扩展名。

ffmpeg()说明:

当你调用 ffmpeg() 时,实际上创建了一个 ffmpeg 实例。这个实例可以用来设置输入文件、输出文件以及一系列的处理选项。

ffmpeg() 返回的是一个 Command 对象,这个对象包含了用于设置和执行 ffmpeg 命令的方法。这些方法可以链接起来形成一个流式操作链。

  • .input():指定输入文件路径
  • .output():指定输出文件路径
  • .on()、.once():监听事件,比如完成、错误等
  • .run():执行ffmpeg命令
  • .cancel():取消正在运行的命令
  • .getCommand():获取将要执行的完整命令字符串

典型的ffmpeg命令执行流程

  1. 初始化:创建 ffmpeg 示例并指定输入文件
  2. 设置输出文件:使用 .output() 方法来设置文件路径
  3. 添加命令行参数:使用 .addOption() 或者链式调用 .option() 方法来添加额外的 ffmpeg参数
  4. 监听事件:监听 end error 事件来处理命令执行的结果
  5. 执行命令:调用 .run() 方法来开始执行命令

 

routers =》index.js

var express = require('express');
var router = express.Router();router.use('/user', require('./users'));module.exports = router;

 app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');var indexRouter = require('./routes/index');var app = express();// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));// 使用cors解决跨域问题
app.use(require('cors')());app.use('/', indexRouter);// catch 404 and forward to error handler
app.use(function (req, res, next) {next(createError(404));
});// error handler
app.use(function (err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

http://www.lryc.cn/news/459321.html

相关文章:

  • 5分钟了解docker的Swarm机制
  • python实现ppt转pdf
  • VS2017 编译 SQLite3 动态库
  • Linux运维_Apache更改默认网站目录
  • QT QString学习笔记
  • 4.stm32 GPIO输入
  • GPT系列
  • Chromium 前端window对象c++实现定义
  • 【力扣算法题】每天一道,健康生活
  • Android Camera系列(四):TextureView+OpenGL ES+Camera
  • 03 django管理系统 - 部门管理 - 部门列表
  • L1 Sklearn 衍生概念辨析 - 回归/分类/聚类/降维
  • 【畅捷通-注册安全分析报告】
  • TCP IP网络编程
  • libssh2编译部署详解
  • IPv4数据报的首部格式 -计算机网络
  • 小米电机与STM32——CAN通信
  • 2.2.ReactOS系统KSERVICE_TABLE_DESCRIPTOR结构体的声明
  • 前端接口报500如何解决 | 发生的原因以及处理步骤
  • 图书馆自习室座位预约管理微信小程序+ssm(lw+演示+源码+运行)
  • 谷歌-BERT-第一步:模型下载
  • FPGA实现PCIE采集电脑端视频缩放后转千兆UDP网络输出,基于XDMA+PHY芯片架构,提供3套工程源码和技术支持
  • Hi3061M开发板——系统时钟频率
  • C++入门基础知识110—【关于C++ if...else 语句】
  • 基于YOLO11深度学习的非机动车驾驶员头盔检测系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测、卷积神经网络
  • 图像分类-demo(Lenet),tensorflow和Alexnet
  • excel 单元格嵌入图片
  • GitHub简介与安装使用入门教程
  • HTML(五)列表详解
  • SparkSQL介绍及使用