🤬 一战落败
无数个日日夜夜,当我们在社区 Blog 中挥洒笔墨写作时,或多或少都遇到过这样一个问题:
当你想在文章中插入一个视频,用更直观的方式展示技术细节或操作流程时,却发现:
系统只允许从指定视频平台选择,而不支持直接上传本地视频。
这就很让人头大。
我只是想展示几个几秒钟的小片段,根本不值得专门去某个平台上传一条视频。于是很多人选择——放弃。
或者另辟蹊径:
👉 把视频转换成 GIF,再作为图片上传。
这听起来是个不错的解决方案——但实际体验却往往是这样的:
- 仅可免费体验几次
- 导出 GIF 带水印
- 想要去水印?——充钱!
一句话总结:
这些网站不是帮你做图,是想让你“入坑”。
🫡 二战转折
既然如此,那就自己动手!
自己开发一个 🎬 “视频转 GIF” 浏览器插件
一. 设计思路
graph TD
用户操作 --> 点击插件
点击插件 --> 文件选择
文件选择 --> 设置生成参数
设置生成参数 --> 帧率-FPS
设置生成参数 --> 像素尺寸-分辨率
设置生成参数 --> 画质-Quality
设置生成参数 --> 时长截取-Duration
设置生成参数 --> 点击生成-GIF
点击生成-GIF --> gif.js处理视频帧
gif.js处理视频帧 --> 生成-GIF文件流
生成-GIF文件流 --> 预览生成效果
生成-GIF文件流 --> 拖曳上传
生成-GIF文件流 --> 一键下载-无水印GIF
这个流程图展示了 视频转 GIF 浏览器插件 的操作流程:
- 用户首先 选择本地视频,可以通过文件选择上传。
- 接着在 设置生成参数 阶段,用户可调整 帧率-FPS、像素尺寸-分辨率、画质-Quality、时长截取->Duration。
- 完成参数设置后,点击 生成 GIF,由
gif.js处理视频帧生成 GIF 文件流。- 最后,用户可以 预览生成效果,满意后直接进行 拖曳上传 或一键下载 无水印 GIF。
二. 实现流程
1. 项目结构确立
GifForge/
├─ manifest.json # 插件清单文件(必须)
├─ popup.html # 弹出界面 HTML
├─ popup.js # 弹出界面 JS
├─ popup.css # 弹出界面样式
├─ icons/ # 图标文件夹
│ ├─ icon16.png
│ ├─ icon48.png
│ └─ icon128.png
├─ lib/ # 第三方库或依赖(如 gif.js)
│ ├─ gif.js
| └─ gif.worker.js
└─ assets/ # 其他资源(如图片、示例视频等)
2. 插件清单文件配置
{
"manifest_version": 3,
"name": "GifForge",
"version": "1.0",
"description": "从本地上传视频文件,按要求提取帧,生成GIF并保存到本地",
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"permissions": []
}
| 字段 | 说明 | 示例 / 备注 |
|---|---|---|
manifest_version | 表示使用的 Manifest 版本。Chrome/Edge 推荐 V3,V3 与 V2 在后台脚本、权限和服务工作者加载方式上有区别。 | 3 |
name | 插件名称,在浏览器扩展管理界面、工具栏、商店中显示。 | "VideoToGif" |
version | 插件版本号,便于发布更新。遵循 主版本号.次版本号.修订号 规则。 | "1.0.0" |
description | 插件描述,告诉用户插件的功能。在浏览器扩展管理页面和商店中显示。 | "从本地上传视频文件,按要求提取帧,生成 GIF 并保存到本地" |
action | 配置点击浏览器工具栏图标时的行为。 - default_popup:指定弹出页面 HTML 文件,例如 popup.html。- default_icon:不同尺寸图标,用于工具栏显示。 | "default_popup": "popup.html" |
icons | 插件图标,用于扩展管理界面、Chrome Web Store 等。建议提供 16px、48px、128px 三种尺寸以适配不同场景。 | "16": "icons/icon16.png" |
permissions | 插件所需权限列表。当前示例为空数组 [],可根据需要添加:- "storage":访问浏览器本地存储- "activeTab":访问当前标签页内容- "tabs":获取或操作浏览器标签页- "downloads":下载文件 | ["storage","downloads"] |
| 可选扩展字段 | 提高功能: - content_scripts:自动注入的脚本,可操作指定网页的 DOM。- background:后台脚本或服务工作者,处理全局任务。- web_accessible_resources:声明可被页面访问的资源,如 worker 脚本。 | - |
3. 弹出界面设计
<!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="popup.css">
</head>
<body>
<div class="container">
<h1>视频转GIF工具</h1>
<div class="file-input">
<label for="videoFile">选择视频文件</label>
<input type="file" id="videoFile" accept="video/*">
</div>
<div class="settings">
# 设置选项...
</div>
<div class="buttons">
<button id="generateBtn" disabled>生成GIF</button>
<button id="downloadBtn" disabled>下载GIF</button>
</div>
<div class="error" id="errorMsg"></div>
<div class="loading" id="loading">
<p>正在处理,请稍候...</p>
</div>
<div class="preview" id="preview">
<h3>预览</h3>
<div id="previewContainer">
<img id="previewImage" src="" alt="GIF预览">
</div>
</div>
</div>
</div>
</body>
</html>
4. 集成 gif.js 库
gif.js 库里有两个核心文件 gif.js 和 gif.worker.js 是我们开发所必需的。
我们可以在GitHub中下载这两个文件,放置在项目中,以供调用。
地址: github.com/jnordberg/g…
① gif.js作用
-
核心库文件,提供主接口
GIF,用于创建 GIF 实例、设置参数和控制生成流程。 -
它主要做两件事:
- 接收帧数据(canvas/image/video)
- 将帧传给
gif.worker.js处理
-
一般会在 popup.js / 前端页面脚本 中引用。
示例用法:
const gif = new GIF({
workers: 2, // 启动多少个 worker 线程
quality: 10, // 图像质量
width: 320,
height: 240
});
// 添加帧
gif.addFrame(canvasElement, {delay: 200});
// 监听完成
gif.on('finished', function(blob) {
const url = URL.createObjectURL(blob);
downloadLink.href = url;
});
② gif.worker.js作用
- Web Worker 文件,在独立线程中处理图像压缩、颜色量化、GIF 编码等耗时任务。
- 优势:不会阻塞主线程,保持页面响应流畅。
gif.js内部会自动通过Worker加载它,无需手动调用。- 注意:路径必须正确,否则
Worker无法加载,GIF 生成失败。
在插件中一般放在 lib/ 或 assets/ 文件夹,并在初始化 GIF 时指定路径:
const gif = new GIF({
workers: 2,
workerScript: 'lib/gif.worker.js', // 指定 worker 文件路径
quality: 10
});
5. 转化逻辑实现
① 选择视频文件
用户通过文件选择或拖拽上传本地视频。
const videoFileInput = document.getElementById('videoFile');
videoFileInput.addEventListener('change', () => {
if (videoFileInput.files.length > 0) generateBtn.disabled = false;
else generateBtn.disabled = true;
downloadBtn.disabled = true;
preview.style.display = 'none';
gifUrl = null;
});
② 设置生成参数
包括帧率(FPS)、画质(Quality)、宽度(Width)、截取时长(Duration)。
const fps = parseInt(fpsInput.value); // 帧率
const quality = parseInt(qualityInput.value); // 画质
const width = parseInt(widthInput.value); // 宽度
const duration = parseInt(durationInput.value); // 截取时长
💡 高度由来
当用户只设置 GIF 的 宽度 时,视频的 高度 会根据原视频的宽高比例自动计算,从而保证生成的 GIF 不会变形。
计算公式:
代码示例:
// 计算原视频高宽比 const aspectRatio = video.videoHeight / video.videoWidth; // 根据宽度自适应高度 canvas.height = Math.round(width * aspectRatio);
③ 初始化视频和 Canvas
创建隐藏的 <video> 元素读取视频帧,创建 <canvas> 用于绘制帧数据。
async function initVideoAndCanvas() {
video = document.createElement('video');
video.autoplay = false;
video.muted = true;
video.loop = false;
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
}
④ 逐帧提取并生成 GIF
const gif = new GIF({
workers: 2,
quality: quality,
width: width,
height: Math.round(width * aspectRatio),
workerScript: 'lib/gif.worker.js'
});
function addFrame(currentFrame) {
if (currentFrame >= totalFrames) {
gif.render();
return;
}
video.currentTime = currentFrame / fps;
setTimeout(() => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
gif.addFrame(canvas, { copy: true, delay: 1000 / fps });
addFrame(currentFrame + 1);
}, 50);
}
按用户
设置的帧率循环视频时间。
将每帧绘制到 Canvas 并添加到 GIF 编码器。
使用gif.js在 Worker 中编码生成GIF 文件流。
5. 预览与下载
gif.on('finished', blob => {
const url = URL.createObjectURL(blob);
previewImage.src = url;
downloadBtn.disabled = false;
});
downloadBtn.addEventListener('click', () => {
if (gifUrl) {
const a = document.createElement('a');
a.href = gifUrl;
a.download = 'output.gif';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
});
将生成的 GIF 显示在
预览区域。
启用下载按钮,用户可保存GIF 文件。
😎 成功上岸
🎉🎉🎉 开发完成之后,咱们直接开始实装测试!
一. 浏览器加载插件
加载插件流程:
- 打开浏览器,输入
浏览器名称://extensions/进入扩展程序页面
(如:edge://extensions/)- 开启右上角的 开发者模式
- 点击 加载已解压的扩展程序
- 选择插件所在的文件夹(vedioToGif文件夹)
- 插件安装成功后,会在浏览器右上角显示图标
二. 插件测试
① 插件使用示例
完整展示
本插件的 GIF 动画效果,并由自身生成。
② 同一 MP4视频 不同参数下的 GIF
|
16px 10画质 10帧率 5时长 |
48px 10画质 10帧率 5时长 |
128px 1画质 1帧率 5时长 |
|
128 像素 4 画质 4 帧率 5时长 |
128像素 7画质 7帧率 5时长 |
128像素 10画质 10帧率 5时长 |
源码
请各位 彦祖 给我点个👍