优化使用 Flask 构建视频转 GIF 工具
优化使用 Flask 构建视频转 GIF 工具
优化后的项目概述
在优化后的版本中,我们将实现以下功能:
- 可设置每个 GIF 的帧率和大小:用户可以选择 GIF 的帧率和输出大小。
- 改进的用户界面:使用更现代的设计使界面更美观、整洁。
- 自定义生成的 GIF 文件名:用户可以为每个视频设置开始时间和持续时间。
优化后的项目结构
your_project/
│
├── app_plus.py # 优化后的 Flask 应用
├── input_videos/ # 上传视频的文件夹
├── output_gifs/ # 输出 GIF 的文件夹
└── templates/└── index_plus.html # 优化后的 HTML 前端页面
Flask 应用代码 (app_plus.py)
from flask import Flask, request, render_template, redirect, url_for, send_from_directory
import subprocess
import osapp = Flask(__name__)
app.config['UPLOAD_FOLDER'] = './input_videos/'
app.config['OUTPUT_FOLDER'] = './output_gifs/'# 确保上传和输出文件夹存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['OUTPUT_FOLDER'], exist_ok=True)def convert_video_to_gif(input_video_path, output_gif_path, start_time, duration, fps, scale):command = ['ffmpeg','-ss', str(start_time),'-t', str(duration),'-i', input_video_path,'-vf', f'fps={fps},scale={scale}:-1:flags=lanczos','-c:v', 'gif',output_gif_path]subprocess.run(command)@app.route('/', methods=['GET', 'POST'])
def index():if request.method == 'POST':video_files = request.files.getlist('video_files')start_times = request.form.getlist('start_times')durations = request.form.getlist('durations')fps = request.form['fps']scale = request.form['scale']custom_name = request.form['custom_name'] # 获取自定义文件名for index, video_file in enumerate(video_files):if video_file:input_video_path = os.path.join(app.config['UPLOAD_FOLDER'], video_file.filename)# 使用用户提供的自定义文件名生成 GIF 文件output_gif_path = os.path.join(app.config['OUTPUT_FOLDER'], f"{custom_name}_{index}.gif")video_file.save(input_video_path)convert_video_to_gif(input_video_path, output_gif_path, start_times[index], durations[index], fps, scale)return redirect(url_for('index')) # 重定向回主页return render_template('index_plus.html')@app.route('/output_gifs/<filename>')
def send_gif(filename):return send_from_directory(app.config['OUTPUT_FOLDER'], filename)if __name__ == '__main__':app.run(debug=True)
HTML 页面代码 (index_plus.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>视频转GIF工具</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"><style>body {font-family: 'Arial', sans-serif;margin: 0;padding: 0;background-color: #f0f0f0;color: #333;}.container {max-width: 800px;margin: 50px auto;padding: 30px;background: white;border-radius: 10px;box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);text-align: center;}h1 {color: #4CAF50;margin-bottom: 20px;}input[type="file"], input[type="number"], input[type="text"] {margin: 10px 0;padding: 15px;width: calc(100% - 30px);border: 1px solid #ccc;border-radius: 5px;transition: border-color 0.3s;}input[type="file"]:hover, input[type="number"]:hover, input[type="text"]:hover {border-color: #4CAF50;}button {margin: 20px 0;padding: 15px;width: 100%;background-color: #4CAF50;color: white;border: none;border-radius: 5px;cursor: pointer;transition: background-color 0.3s;}button:hover {background-color: #45a049;}footer {margin-top: 30px;font-size: 14px;color: #777;}.video-input {margin-bottom: 20px;border: 1px solid #ccc;border-radius: 5px;padding: 10px;}.video-input div {margin-bottom: 10px;}@media (max-width: 600px) {.container {padding: 20px;}h1 {font-size: 24px;}}</style>
</head>
<body><div class="container"><h1>视频转GIF工具</h1><form action="/" method="post" enctype="multipart/form-data"><div class="video-input"><input type="file" name="video_files" accept="video/*" multiple required><input type="number" name="start_times" placeholder="开始时间(秒)" required><input type="number" name="durations" placeholder="持续时间(秒)" required></div><label for="fps">帧率 (fps):</label><input type="number" name="fps" placeholder="例如: 10" required><label for="scale">输出大小 (宽度):</label><input type="text" name="scale" placeholder="例如: 320" required><label for="custom_name">自定义文件名:</label><input type="text" name="custom_name" placeholder="例如: my_gif" required><button type="submit">转换为 GIF</button></form><footer><p>© 2025 无限大</p></footer></div>
</body>
</html>
说明
-
Flask 应用 (
app_plus.py):- 设置上传和输出文件夹。
- 提供一个函数
convert_video_to_gif,用来调用 FFmpeg 生成 GIF 文件。 - 在
/路由中处理文件上传和 GIF 生成。 - 获取用户输入的自定义 GIF 文件名,生成的文件名为
自定义名字 + 索引 + .gif以避免重名问题。
-
HTML 界面 (
index_plus.html):- 创建一个用户输入界面,允许用户上传视频、设置时间参数、帧率和输出大小。
- 添加输入框让用户输入自定义 GIF 文件名。
依赖
确保安装了 Flask 和 FFmpeg:
pip install Flask
并确保 FFmpeg 已正确安装并在系统路径中。
启动和测试
运行 Flask 应用:
python app_plus.py
在浏览器中访问 http://127.0.0.1:5000/ 测试功能。
相关文章:
优化使用 Flask 构建视频转 GIF 工具
优化使用 Flask 构建视频转 GIF 工具 优化后的项目概述 在优化后的版本中,我们将实现以下功能: 可设置每个 GIF 的帧率和大小:用户可以选择 GIF 的帧率和输出大小。改进的用户界面:使用更现代的设计使界面更美观、整洁。自定义…...
spring cloud如何实现负载均衡
在Spring Cloud中,实际上并没有直接支持lb:\\这样的URL前缀来自动解析为负载均衡的服务地址。lb:\\这样的表示可能是在某些特定框架、文档或示例中自定义的,但它并不是Spring Cloud官方API或规范的一部分。 Spring Cloud实现负载均衡的方式通常依赖于服…...
leetcode19-删除链表的第n结点
leetcode 19 思路 要删除倒数第n个元素,那么就要找到倒数第n1个元素,那么我们需要两个指针来记录,首先快指针需要先走n1步,然后快慢指针一起进行移动,直到快指针为null的时候,此时慢指针恰好走到倒数第n…...
软件测试—— 接口测试(HTTP和HTTPS)
软件测试—— 接口测试(HTTP和HTTPS) HTTP请求方法GET特点使用场景URL结构URL组成部分URL编码总结 POST特点使用场景请求结构示例 请求标头和响应标头请求标头(Request Headers)示例请求标头 响应标头(Response Header…...
3.1 Go函数调用过程
在 Go 语言中,函数调用的核心机制依赖于内存的栈区分配和指针操作,理解这一原理有助于掌握函数的执行过程。 1. 内存结构概述 在 Go 程序编译成可执行文件并启动后,操作系统会为其分配进程内存,进程内存主要分为以下区域&#x…...
TDengine 做 Apache SuperSet 数据源
Apache Superset 是一个现代的企业级商业智能(BI)Web 应用程序,主要用于数据探索和可视化。它由 Apache 软件基金会支持,是一个开源项目,它拥有活跃的社区和丰富的生态系统。Apache Superset 提供了直观的用户界面…...
08_游戏启动逻辑
1.GameRoot.cs 控制 服务层Svc.cs 和业务层Sys.cs 的初始化 创建脚本GameRoot.cs(游戏入口 已进入就初始化各个系统) 创建资源加载服务.cs Res 将服务层Svc设置成单例类所以需要挂载在GameRoot身上,这样就可以通过GameRoot来调各个服务 接…...
Ardupilot开源无人机之Geek SDK进展2024-2025
Ardupilot开源无人机之Geek SDK进展2024-2025 1. 源由2. 状态3. TODO3.1 【进行中】跟踪目标框3.2 【暂停】onnxruntime版本3.3 【完成】CUDA 11.8版本3.4 【完成】pytorch v2.5.1版本3.5 【未开始】Inference性能3.6 【未开始】特定目标集Training 4. Extra-Work4.1 【完成】C…...
在K8S中,如果后端NFS存储的IP发送变化如何解决?
在Kubernetes中,如果后端NFS存储的IP地址发生了变化,您需要更新与之相关的Peristent Volume(PV)或Persistent Volume Claim(PVC)以及StorageClass中关于NFS服务器IP的配置信息,确保K8S集群内的Pod能够正确连接到新的NFS存储位置。解决方案如下…...
模拟飞行入坑(五) P3D 多通道视角配置 viewgroup
背景: P3D进行多个屏幕显示的时候,如果使用英伟达自带的屏幕融合成一个屏,或者使用P3D单独拉伸窗口,会使得P3D的画面被整体拉伸,又或者,当使用Multichannel进行多个设备联动时,视角同步组合需要配置&#…...
【springboot集成knife4j】
SpringBoot集成knife4j Knife4j是为Java MVC框架集成Swagger生成API文档的一套增强解决方案,它基于Swagger原有的基础上进行了一些改进和增强,提供了更简洁的UI界面,同时支持更多的自用化配置。下面是在Spring Boot项目中集成Knife4j的基本步…...
GPUStack使用
1. 概述 官网:https://github.com/gpustack Open-source GPU cluster manager for running large language models(LLMs) https://github.com/gpustack/gpustack,Manage GPU clusters for running AI models GPUStack 是一个用于运行 AI 模型的开源 GPU 集群管理器。 官…...
如何选择一款助贷获客系统?
做助贷的销售们,一天打几百个电话,跑各种新媒体平台评论区偷流量,每天忙得昏天黑地,也没有多少客户。没有精准数据,助贷销售着急,公司也着急,每天让员工加班找客户,但是巧妇难为无米…...
GDB相比IDE有什么优点
GDB(GNU Debugger)相比于集成开发环境(IDE)具有一些独特的优点,主要体现在其灵活性、可定制性和低级控制能力。具体来说,GDB有以下几个优点: 1. 轻量级且无依赖 GDB是一个命令行工具,不依赖于任何复杂的图形界面或大型库,这使得它非常适合在资源受限的环境中使用,比…...
介绍用于机器学习的 Fashion-MNIST 数据集
介绍用于机器学习的 Fashion-MNIST 数据集 为什么要研究数据集? 让我们首先思考一下为什么要花时间研究数据集的问题。数据是深度学习的主要成分,虽然作为神经网络程序员的任务是让我们的神经网络从我们的数据中学习,但我们仍然有责任了解我…...
【GitHub】登录时的2FA验证
一、如何进行2FA认证 1.在你的浏览器中下载 Authenticator身份验证插件 2.使用身份验证器添加凭证 2.1 使用身份验证器扫描验证二维码 选择扫描二维码...
CSDN年度回顾:技术征途上的坚实步伐
嘿,时光过得可真快呀,就像那匹跑得飞快的白马,嗖的一下,2024 年的日历就这么悄无声息地翻到了最后一页。这会儿我回头看看在 CSDN 上度过的这一年,心里那叫一个感慨万千,满满的都是喜悦,就像心里…...
Kotlin Bytedeco OpenCV 图像图像57 图像ROI
Kotlin Bytedeco OpenCV 图像图像57 图像ROI 1 添加依赖2 测试代码3 测试结果 1 添加依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns"http://maven.apache.o…...
支持大功率输出高速频闪的图像处理用光源控制器
机器视觉系统中的光源控制器在确保图像质量、提高系统稳定性、降低能耗以及方便系统扩展和升级等方面发挥着重要作用。它可提供稳定光源,调节参数,另外具有操作便捷性。 下面我们来看Gardasoft的光源控制器,Gardasoft拥有作为图像处理用LED光…...
《从入门到精通:蓝桥杯编程大赛知识点全攻略》(五)-数的三次方根、机器人跳跃问题、四平方和
本博客将详细探讨如何通过二分查找算法来解决这几个经典问题。通过几个实际的例子,我们将展示如何在这些问题中灵活应用二分查找,优化计算过程,并在面对大数据量时保持高效性。 目录 前言 数的三次方根 算法思路 代码如下 机器人跳跃问题…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
