如何在React.js项目中使用最新版@ffmpeg/ffmpeg?含添logo需求
最新版@ffmpeg/ffmpeg在React中的使用指南(含视频加Logo示例)
一、核心API变化总结
对比旧版,新版API做了轻量化重构,核心差异如下:
- 实例创建:旧版用
createFFmpeg()工厂函数,新版直接实例化FFmpeg类 - 文件处理:旧版的
fetchFile被移除,直接用原生File/Blob对象或fetch获取的二进制数据即可 - 命令执行:旧版的
run()方法替换为exec(),直接传入FFmpeg命令行参数数组 - 保留的核心方法:
load()(加载FFmpeg核心库)、writeFile()(写入文件到虚拟文件系统)、readFile()(读取处理后文件)、terminate()(释放资源)
二、React项目完整实现(视频加Logo)
1. 安装依赖
新版需要单独安装FFmpeg核心库:
npm install @ffmpeg/ffmpeg @ffmpeg/core
2. 完整组件示例
以下是实现视频加Logo的React函数组件:
import { useState, useRef, useEffect } from 'react'; import { FFmpeg } from '@ffmpeg/ffmpeg'; const VideoLogoAdder = () => { const ffmpegRef = useRef(new FFmpeg()); const [isLoading, setIsLoading] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const [videoFile, setVideoFile] = useState(null); const [logoFile, setLogoFile] = useState(null); const [resultUrl, setResultUrl] = useState(null); // 加载FFmpeg核心 const loadFFmpeg = async () => { if (ffmpegRef.current.loaded) return; setIsLoading(true); // 可替换为CDN地址,比如'https://unpkg.com/@ffmpeg/core@0.12.6/dist/ffmpeg-core.js' await ffmpegRef.current.load({ coreURL: '/ffmpeg-core.js' }); setIsLoading(false); }; // 处理视频加Logo const processVideo = async () => { if (!videoFile || !logoFile) return; setIsProcessing(true); try { // 1. 将本地文件写入FFmpeg虚拟文件系统 await ffmpegRef.current.writeFile('input.mp4', await videoFile.arrayBuffer()); await ffmpegRef.current.writeFile('logo.png', await logoFile.arrayBuffer()); // 2. 执行FFmpeg加Logo命令 // overlay=10:10 表示Logo放在左上角,距离左、上各10px,可自行调整参数 await ffmpegRef.current.exec([ '-i', 'input.mp4', '-i', 'logo.png', '-filter_complex', 'overlay=10:10', '-c:v', 'libx264', // 视频编码格式 '-c:a', 'copy', // 音频直接复制,避免重新编码 'output.mp4' ]); // 3. 读取处理后的文件并生成预览URL const outputData = await ffmpegRef.current.readFile('output.mp4'); const blob = new Blob([outputData], { type: 'video/mp4' }); const url = URL.createObjectURL(blob); setResultUrl(url); } catch (err) { console.error('处理失败:', err); } finally { setIsProcessing(false); } }; // 组件卸载时清理资源 useEffect(() => { return () => { if (ffmpegRef.current) { ffmpegRef.current.terminate(); } if (resultUrl) { URL.revokeObjectURL(resultUrl); } }; }, [resultUrl]); return ( <div style={{ maxWidth: 800, margin: '0 auto', padding: '20px' }}> <h2>视频添加Logo工具</h2> <button onClick={loadFFmpeg} disabled={isLoading} style={{ padding: '8px 16px', marginBottom: '20px' }} > {isLoading ? '加载FFmpeg中...' : '初始化FFmpeg'} </button> <div style={{ marginBottom: '20px' }}> <input type="file" accept="video/*" onChange={(e) => setVideoFile(e.target.files[0])} style={{ marginRight: '10px' }} /> <input type="file" accept="image/png,image/jpeg" onChange={(e) => setLogoFile(e.target.files[0])} /> </div> <button onClick={processVideo} disabled={isLoading || isProcessing || !videoFile || !logoFile} style={{ padding: '8px 16px', backgroundColor: '#2196F3', color: 'white', border: 'none', borderRadius: '4px' }} > {isProcessing ? '处理中...' : '给视频添加Logo'} </button> {resultUrl && ( <div style={{ marginTop: '30px' }}> <h3>处理结果</h3> <video controls src={resultUrl} style={{ width: '100%' }} /> </div> )} </div> ); }; export default VideoLogoAdder;
三、关键注意事项
- 核心库加载:必须先调用
load()方法加载FFmpeg核心,否则无法执行任何命令。可以将核心文件放在项目public目录下,或使用CDN地址 - 虚拟文件系统:所有文件操作都在FFmpeg的虚拟FS中进行,写入时自定义文件名,读取时对应即可
- 性能优化:浏览器端视频处理资源消耗大,务必显示加载/处理状态,避免用户误操作
- 资源清理:组件卸载时调用
terminate()释放FFmpeg资源,同时revoke Blob URL防止内存泄漏 - 命令参数:FFmpeg的滤镜参数(比如
overlay)可以根据需求调整,比如overlay=W-w-10:10表示右上角放置Logo
内容的提问来源于stack exchange,提问作者Muzammil Raza
相关产品推荐
相关产品推荐

