如何在基于Node.js的fluent-ffmpeg视频编辑中结合React.js实现进度条
Hey there! I’ve built this exact workflow before—combining fluent-ffmpeg on Node.js with a React progress bar feels tricky at first, but it’s totally manageable with real-time communication. Let’s break it down step by step:
First, you need to capture ffmpeg’s progress events and send them to the frontend. WebSockets (using Socket.io) are perfect here because they let you push updates in real time without the frontend polling constantly.
Step 1.1 Install Dependencies
First, install the required packages:
npm install fluent-ffmpeg express socket.io
(Make sure you have ffmpeg installed on your server too—fluent-ffmpeg is just a wrapper, not the actual binary.)
Step 1.2 Set Up the Server
Here’s a minimal server example that handles video processing and emits progress via Socket.io:
const express = require('express'); const ffmpeg = require('fluent-ffmpeg'); const { Server } = require('socket.io'); const http = require('http'); const app = express(); const server = http.createServer(app); const io = new Server(server, { cors: { origin: "http://localhost:3000", // Your React app URL methods: ["GET", "POST"] } }); // Endpoint to trigger video processing app.post('/process-video', (req, res) => { // Replace with your input/output paths const inputPath = './input.mp4'; const outputPath = './output.mp4'; const videoProcess = ffmpeg(inputPath) .output(outputPath) .on('progress', (progress) => { // Emit progress to all connected clients (or target a specific client) io.emit('video-progress', { percent: Math.round(progress.percent) }); console.log(`Processing: ${progress.percent}% done`); }) .on('end', () => { io.emit('video-progress', { percent: 100, done: true }); res.status(200).send('Video processing complete!'); }) .on('error', (err) => { io.emit('video-error', { message: err.message }); res.status(500).send(`Error processing video: ${err.message}`); }); videoProcess.run(); }); io.on('connection', (socket) => { console.log('A client connected'); socket.on('disconnect', () => { console.log('Client disconnected'); }); }); server.listen(4000, () => { console.log('Server running on port 4000'); });
Now, let’s build the React component that connects to the Socket.io server, triggers the video processing, and displays the progress.
Step 2.1 Install Socket.io Client
npm install socket.io-client
Step 2.2 Build the Progress Bar Component
Here’s a functional component using React hooks:
import { useState, useEffect } from 'react'; import io from 'socket.io-client'; const socket = io('http://localhost:4000'); // Your backend URL function VideoProgressBar() { const [progress, setProgress] = useState(0); const [isProcessing, setIsProcessing] = useState(false); const [errorMessage, setErrorMessage] = useState(''); useEffect(() => { // Listen for progress updates socket.on('video-progress', (data) => { setProgress(data.percent); if (data.done) { setIsProcessing(false); } }); // Listen for errors socket.on('video-error', (data) => { setErrorMessage(data.message); setIsProcessing(false); }); // Clean up listeners on unmount return () => { socket.off('video-progress'); socket.off('video-error'); }; }, []); const startProcessing = async () => { setIsProcessing(true); setProgress(0); setErrorMessage(''); try { const response = await fetch('http://localhost:4000/process-video', { method: 'POST', }); if (!response.ok) { throw new Error('Failed to start processing'); } } catch (err) { setErrorMessage(err.message); setIsProcessing(false); } }; return ( <div style={{ padding: '2rem', maxWidth: '600px', margin: '0 auto' }}> <h2>Video Editor Progress</h2> {errorMessage && <p style={{ color: 'red' }}>{errorMessage}</p>} <button onClick={startProcessing} disabled={isProcessing} style={{ padding: '0.5rem 1rem', marginBottom: '1rem' }} > {isProcessing ? 'Processing...' : 'Start Video Edit'} </button> <div style={{ height: '20px', width: '100%', backgroundColor: '#eee', borderRadius: '10px', overflow: 'hidden' }}> <div style={{ height: '100%', width: `${progress}%`, backgroundColor: '#4CAF50', transition: 'width 0.3s ease' }} /> </div> <p style={{ marginTop: '0.5rem' }}>{progress}% Complete</p> </div> ); } export default VideoProgressBar;
- Targeted Progress Updates: In the example above, we emit progress to all clients. For a production app, you’ll want to send updates only to the client that initiated the request—use Socket.io rooms or pass a unique task ID when starting processing, then emit to that specific ID.
- FFmpeg Installation: Double-check that
ffmpegis installed on your server (runffmpeg -versionto confirm). On Linux, you can install it viaapt install ffmpeg; on macOS, usebrew install ffmpeg. - Error Handling: Add more robust error handling (e.g., check if input files exist, handle timeouts for long-running processes).
- State Management: If you’re using a state manager like Redux or Zustand, you can move the progress state there to share it across components.
That’s it! When you click the "Start Video Edit" button, the backend kicks off the ffmpeg process, sends real-time progress to the React frontend, and the progress bar updates smoothly.
内容的提问来源于stack exchange,提问作者Young RichMan

