vue純靜態實現 視頻轉GIF 功能(附源碼)

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔

文章目錄

  • 前言
  • 一、實現后的效果
  • 二、使用步驟
    • 1.引入庫
    • 2.下載or復制出來js
    • 3. 前端實現
  • 總結


前言

一天一個小demo 今天來一個vue純靜態實現 視頻轉GIF 功能

上一篇我們講到了使用html+node.js+sealos實現了一個 多人實時在線聊天的簡單小demo ,這次我們來寫一個 視頻轉換成GIF的小功能 使用到的技術為 vue3 + @ffmpeg 很簡單。


一、實現后的效果

下面是實現的效果,是我錄制視頻后轉換成GIF的效果,當然下面這個GIF就是轉換出來的真實效果哦。
在這里插入圖片描述

二、使用步驟

1.引入庫

代碼如下(初始化一個vue3項目):
我來安裝依賴 下面版本號是我現在demo的版本號

 "@ffmpeg/core": "0.12.4","@ffmpeg/ffmpeg": "0.12.7","@ffmpeg/util": "0.12.1",
npm i  @ffmpeg/core@0.12.4
npm i  @ffmpeg/ffmpeg@0.12.7
npm i  @ffmpeg/util@0.12.1

2.下載or復制出來js

我這里把這些給放到public項目里面了

https://unpkg.com/@ffmpeg/core@0.12.4/dist/esm/ffmpeg-core.js
https://unpkg.com/@ffmpeg/core@0.12.4/dist/esm/ffmpeg-core.wasm
https://unpkg.com/@ffmpeg/core@0.12.4/dist/esm/ffmpeg-core.worker.js

在這里插入圖片描述

3. 前端實現

<template><div class="video-conversion"><div class="hero-section"><h1>視頻轉GIF工具</h1><p class="subtitle">簡單、快速地將視頻轉換為高質量GIF動畫</p></div><div class="content-wrapper"><div class="upload-section" :class="{ 'has-video': videoUrl }"><div class="upload-area" v-if="!videoUrl" @click="triggerFileInput"><el-icon class="upload-icon"><Upload /></el-icon><p class="upload-text">點擊或拖拽視頻文件到這里</p><p class="upload-hint">支持 MP4、WebM、MOV 格式 (最大50MB)</p></div><input type="file" @change="handleFileSelect" accept="video/*" ref="fileInput" class="hidden-input"></div><div v-if="videoUrl" class="preview-container"><div class="video-preview"><div class="video-header"><h3>視頻預覽</h3><el-button type="primary" size="small" @click="triggerFileInput" class="change-video-btn"><el-icon><VideoCamera /></el-icon>更換視頻</el-button></div><video :src="videoUrl" controls ref="videoPreview"></video></div><div class="settings-panel"><h3>轉換設置</h3><div class="settings-group"><el-form :model="settings" label-position="top"><el-form-item label="GIF寬度"><el-slider v-model="width" :min="100" :max="800" :step="10" show-input /></el-form-item><el-form-item label="幀率 (FPS)"><el-slider v-model="fps" :min="1" :max="30" :step="1" show-input /></el-form-item></el-form></div><el-button type="primary" :loading="isConverting" @click="convertToGif" class="convert-btn">{{ isConverting ? '正在轉換...' : '開始轉換' }}</el-button></div></div><div v-if="gifUrl" class="result-section"><div class="result-preview"><h3>預覽</h3><img :src="gifUrl" alt="轉換后的GIF"><div class="action-buttons"><el-button type="success" :href="gifUrl" download="converted.gif" @click="downloadGif">下載GIF</el-button><el-button @click="resetConverter">重新轉換</el-button></div></div></div></div><el-alert v-if="error" :title="error" type="error" show-icon class="error-alert" /></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import { FFmpeg } from '@ffmpeg/ffmpeg'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
import { Upload, VideoCamera } from '@element-plus/icons-vue'const ffmpeg = new FFmpeg()
const loaded = ref(false)
const isConverting = ref(false)
const videoUrl = ref('')
const gifUrl = ref('')
const error = ref('')
const width = ref(480)
const fps = ref(10)
const fileInput = ref(null)const load = async () => {try {const baseURL = window.location.origin;// 修改核心文件的加載方式await ffmpeg.load({coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')});loaded.value = true;console.log('FFmpeg 加載成功');} catch (err) {console.error('FFmpeg 加載錯誤:', err);error.value = '加載轉換工具失敗:' + err.message;}
};// 修改處理文件選擇的方法
const handleFileSelect = (event) => {const file = event.target.files[0]if (!file) returnif (file.size > 50 * 1024 * 1024) {error.value = '文件大小不能超過50MB'return}// 如果已經有之前的視頻URL,先釋放它if (videoUrl.value) {URL.revokeObjectURL(videoUrl.value)}videoUrl.value = URL.createObjectURL(file)gifUrl.value = ''error.value = ''width.value = 480 // 重置設置fps.value = 10
}// 轉換為GIF
const convertToGif = async () => {if (!loaded.value) {error.value = '轉換工具尚未加載完成'return}try {isConverting.value = trueerror.value = ''// 寫入文件到FFmpeg虛擬文件系統const videoFile = await fetch(videoUrl.value)const videoData = await videoFile.arrayBuffer()await ffmpeg.writeFile('input.mp4', new Uint8Array(videoData))// 執行轉換命令await ffmpeg.exec(['-i', 'input.mp4','-vf', `scale=${width.value}:-1:flags=lanczos,fps=${fps.value}`,'-c:v', 'gif','output.gif'])// 讀取轉換后的文件const data = await ffmpeg.readFile('output.gif')const blob = new Blob([data], { type: 'image/gif' })gifUrl.value = URL.createObjectURL(blob)} catch (err) {error.value = '轉換失敗:' + err.message} finally {isConverting.value = false}
}const triggerFileInput = () => {fileInput.value.click()
}const downloadGif = () => {const link = document.createElement('a')link.href = gifUrl.valuelink.download = 'converted.gif'document.body.appendChild(link)link.click()document.body.removeChild(link)
}const resetConverter = () => {videoUrl.value = ''gifUrl.value = ''error.value = ''width.value = 480fps.value = 10
}onMounted(() => {load()
})
</script><style scoped>
.video-conversion {max-width: 1200px;margin: 0 auto;padding: 40px 20px;color: #1d1d1f;
}.hero-section {text-align: center;margin-bottom: 60px;
}.hero-section h1 {font-size: 48px;font-weight: 600;margin-bottom: 16px;background: linear-gradient(135deg, #1a1a1a 0%, #4a4a4a 100%);-webkit-background-clip: text;-webkit-text-fill-color: transparent;
}.subtitle {font-size: 24px;color: #86868b;font-weight: 400;
}.content-wrapper {background: white;border-radius: 20px;box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);overflow: hidden;
}.upload-section {padding: 40px;transition: all 0.3s ease;
}.upload-area {border: 2px dashed #d2d2d7;border-radius: 12px;padding: 40px;text-align: center;cursor: pointer;transition: all 0.3s ease;
}.upload-area:hover {border-color: #0071e3;background: rgba(0, 113, 227, 0.05);
}.upload-icon {font-size: 48px;color: #86868b;margin-bottom: 20px;
}.upload-text {font-size: 20px;color: #1d1d1f;margin-bottom: 8px;
}.upload-hint {font-size: 14px;color: #86868b;
}.hidden-input {display: none;
}.preview-container {display: grid;grid-template-columns: 2fr 1fr;gap: 30px;padding: 30px;background: #f5f5f7;
}.video-preview {background: white;padding: 20px;border-radius: 12px;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}.video-preview video {width: 100%;border-radius: 8px;
}.settings-panel {background: white;padding: 30px;border-radius: 12px;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}.settings-panel h3 {font-size: 20px;margin-bottom: 24px;color: #1d1d1f;
}.settings-group {margin-bottom: 30px;
}.convert-btn {width: 100%;height: 44px;font-size: 16px;
}.result-section {padding: 40px;background: white;
}.result-preview {text-align: center;
}.result-preview img {max-width: 100%;border-radius: 12px;margin: 20px 0;box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}.action-buttons {display: flex;gap: 16px;justify-content: center;margin-top: 24px;
}.error-alert {position: fixed;top: 20px;right: 20px;z-index: 1000;
}.video-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 15px;
}.video-header h3 {margin: 0;font-size: 18px;color: #1d1d1f;
}.change-video-btn {display: flex;align-items: center;gap: 5px;padding: 8px 15px;font-size: 14px;
}.change-video-btn .el-icon {font-size: 16px;
}.has-video .upload-area {border: 2px solid #d2d2d7;margin-bottom: 20px;
}.has-video .upload-area:hover {border-color: #0071e3;
}@media (max-width: 768px) {.preview-container {grid-template-columns: 1fr;}.hero-section h1 {font-size: 32px;}.subtitle {font-size: 18px;}
}
</style>

總結

以上就是今天要講的內容,本文僅僅簡單介紹了@ffmpeg 庫 的使用,而@ffmpeg提供了大量能使我們快速便捷地處理視頻數據的函數和方法。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/895375.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/895375.shtml
英文地址,請注明出處:http://en.pswp.cn/news/895375.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

因果機器學習(CausalML)前沿創新思路

結合了傳統因果推斷與機器學習的因果機器學習是目前AI領域的前沿研究方向&#xff0c;其核心優勢在于將因果邏輯融入數據驅動模型&#xff0c;從根本上解決了傳統方法的缺陷。因此&#xff0c;它也是突破傳統機器學習瓶頸的關鍵方向&#xff0c;不僅當下熱度高&#xff0c;在未…

【CubeMX+STM32】SD卡 U盤文件系統 USB+FATFS

本篇&#xff0c;將使用CubeMXKeil, 創建一個 USBTF卡存儲FatFS 的虛擬U盤讀寫工程。 目錄 一、簡述 二、CubeMX 配置 SDIO DMA FatFs USB 三、Keil 編輯代碼 四、實驗效果 串口助手&#xff0c;實現效果&#xff1a; U盤&#xff0c;識別效果&#xff1a; 一、簡述 上…

docker nginx 配置文件詳解

在平常的開發工作中&#xff0c;我們經常需要訪問靜態資源&#xff08;圖片、HTML頁面等&#xff09;、訪問文件目錄、部署項目時進行負載均衡等。那么我們就會使用到Nginx&#xff0c;nginx.conf 的配置至關重要。那么今天主要結合訪問靜態資源、負載均衡等總結下 nginx.conf …

Ubuntu 下 nginx-1.24.0 源碼分析 - ngx_atomic_cmp_set 函數

目錄 修正 執行 ./configure 命令時&#xff0c;輸出&#xff1a; checking for OS Linux 6.8.0-52-generic x86_64 checking for C compiler ... found using GNU C compiler gcc version: 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) 所以當前環境是 x86_64 于是在 src…

在 Go 中實現事件溯源:構建高效且可擴展的系統

事件溯源&#xff08;Event Sourcing&#xff09;是一種強大的架構模式&#xff0c;它通過記錄系統狀態的變化&#xff08;事件&#xff09;來重建系統的歷史狀態。這種模式特別適合需要高可擴展性、可追溯性和解耦的系統。在 Go 語言中&#xff0c;事件溯源可以通過一些簡單的…

大數據Orc文件生成與讀取

ORC(Optimized Row Columnar)是Hadoop生態系統中一種高效的列式存儲文件格式,其主要特性包括高效壓縮、快速讀取、以及能夠存儲結構化數據。本文將展示如何使用Java編寫代碼來生成和讀取ORC文件。 一、ORC文件介紹 ORC是一種為Hadoop生態系統優化的列式存儲格式,具有以下…

解讀 Flink Source 接口重構后的 KafkaSource

前言 Apache Kafka 和 Apache Flink 的結合&#xff0c;為構建實時流處理應用提供了一套強大的解決方案[1]。Kafka 作為高吞吐量、低延遲的分布式消息隊列&#xff0c;負責數據的采集、緩沖和分發&#xff1b;而 Flink 則是功能強大的流處理引擎&#xff0c;負責對數據進行實時…

【推理llm論文精讀】DeepSeek V3技術論文_精工見效果

先附上原始論文和效果對比https://arxiv.org/pdf/2412.19437 摘要 (Abstract) DeepSeek-V3是DeepSeek-AI團隊推出的最新力作&#xff0c;一個強大的混合專家&#xff08;Mixture-of-Experts&#xff0c;MoE&#xff09;語言模型。它擁有671B的總參數量&#xff0c;但每個tok…

如何使用Java語言在Idea和Android中分別建立服務端和客戶端實現局域網聊天

手把手教你用Java語言在Idea和Android中分別建立服務端和客戶端實現局域網聊天 目錄 文章目錄 手把手教你用**Java**語言在**Idea**和**Android**中分別建立**服務端**和**客戶端**實現局域網聊天**目錄**[toc]**基本實現****問題分析****服務端**Idea:結構預覽Server類代碼解…

java韓順平最新教程,Java工程師進階

簡介 HikariCP 是用于創建和管理連接&#xff0c;利用“池”的方式復用連接減少資源開銷&#xff0c;和其他數據源一樣&#xff0c;也具有連接數控制、連接可靠性測試、連接泄露控制、緩存語句等功能&#xff0c;另外&#xff0c;和 druid 一樣&#xff0c;HikariCP 也支持監控…

如何在 IDE 里使用 DeepSeek?

近期&#xff0c;阿里云百煉平臺重磅推出 DeepSeek-V3、DeepSeek-R1、DeepSeek-R1-Distill-Qwen-32B 等 6 款模型&#xff0c;進一步豐富其 AI 模型矩陣。與此同時&#xff0c;通義靈碼也緊跟步伐&#xff0c;全新上線模型選擇功能&#xff0c;支持基于百煉的 DeepSeek-V3 和 D…

vue中附件下載及打印功能

1.附件dom 注&#xff1a;fileList是由后臺返回的附件數組&#xff0c;數組中包含附件名稱fileName,附件地址url&#xff0c;附件id等信息 <el-form-item label"附件" style"width: 100% !important;" v-if"modelTypeborrowDetail"><d…

chromium-mojo

https://chromium.googlesource.com/chromium/src//refs/heads/main/mojo/README.md 相關類&#xff1a;https://zhuanlan.zhihu.com/p/426069459 Core:https://source.chromium.org/chromium/chromium/src//main:mojo/core/README.md;bpv1;bpt0 embedder:https://source.chr…

網絡安全技術復習總結

1|0第一章 概論 1.網絡安全發展階段包括四個階段&#xff1a;通信安全、計算機安全、網絡安全、網絡空間安全。 2.2017年6月1日&#xff0c;我國第一部全面規范網絡空間安全的基礎性法律《中華人民共和國網絡安全法》正式實施。 3.2021年 6月10日&#xff0c;《中華人民共和…

基于華為云鏡像加速器的Docker環境搭建與項目部署指南

基于華為云鏡像加速器的Docker環境搭建與項目部署指南 一、安裝Docker1.1 更新系統包1.2 安裝必要的依賴包1.3 移除原有的Docker倉庫配置(如果存在)1.4 添加華為云Docker倉庫1.5 安裝Docker CE1.6 啟動Docker服務1.7 驗證Docker是否安裝成功1.8 添加華為云鏡像加速器地址二、…

在SpringBoot服務器端采購上,如何選擇操作系統、Cpu、內存和帶寬、流量套餐

在Spring Boot服務器端采購時&#xff0c;選擇操作系統、CPU、內存、帶寬和流量套餐需根據應用需求、預算和性能要求綜合考慮。以下是具體建議&#xff1a; 1. 操作系統 Linux發行版&#xff08;如Ubuntu、CentOS&#xff09;&#xff1a;適合大多數Spring Boot應用&#xff…

DedeBIZ系統審計小結

之前簡單審計過DedeBIZ系統&#xff0c;網上還沒有對這個系統的漏洞有過詳盡的分析&#xff0c;于是重新審計并總結文章&#xff0c;記錄下自己審計的過程。 https://github.com/DedeBIZ/DedeV6/archive/refs/tags/6.2.10.zip &#x1f4cc;DedeBIZ 系統并非基于 MVC 框架&…

業務開發 | 基礎知識 | Maven 快速入門

Maven 快速入門 1.Maven 全面概述 Apache Maven 是一種軟件項目管理和理解工具。基于項目對象模型的概念&#xff08;POM&#xff09;&#xff0c;Maven 可以從中央信息中管理項目的構建&#xff0c;報告和文檔。 2.Maven 基本功能 因此實際上 Maven 的基本功能就是作為 Ja…

人工智能之推薦系統實戰系列(協同過濾,矩陣分解,FM與DeepFM算法)

一.推薦系統介紹和應用 (1)推薦系統通俗解讀 推薦系統就是來了就別想走了。例如在大數據時代中京東越買越想買&#xff0c;抖音越刷越是自己喜歡的東西&#xff0c;微博越刷越過癮。 (2).推薦系統發展簡介 1)推薦系統無處不在&#xff0c;它是根據用戶的行為決定推薦的內容…

2.11 sqlite3數據庫【數據庫的相關操作指令、函數】

練習&#xff1a; 將 epoll 服務器 客戶端拿來用 客戶端&#xff1a;寫一個界面&#xff0c;里面有注冊登錄 服務器&#xff1a;處理注冊和登錄邏輯&#xff0c;注冊的話將注冊的賬號密碼寫入數據庫&#xff0c;登錄的話查詢數據庫中是否存在賬號&#xff0c;并驗證密碼是否正確…