I recently followed a tutorial by Fireship.io going over making a React App that enables a user to input a video file and convert it into a gif. Here is the source GitHub Repo.
The packages used by the project are @ffmpeg/ffmpeg
and @ffmpeg/core
, which take care of converting the video into a GIF (although this can be changed to whatever, like the FFmpeg CLI tool).
I wanted to take this a step further and make it possible for me to convert multiple videos at once, each into their own separate gif, however, I am having trouble running the next task when the first is finished.
Here is documentation I found about the ffmpeg wasm package. I also read this example given by the package providers to have multiple outputs from a single file.
Here is my code (App.jsx):
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg({ log: true });
function App() {
const [ready, setReady] = useState(false);
const [videos, setVideos] = useState([]);
const [gifs, setGifs] = useState([]);
const load = async () => {
await ffmpeg.load();
setReady(true);
};
useEffect(() => {
load();
}, []);
const onInputChange = (e) => {
for (let i = 0; i < e.target.files.length; i++) {
const newVideo = e.target.files[i];
setVideos((videos) => [...videos, newVideo]);
}
};
const batchConvert = async (video) => {
const name = video.name.split('.mp4').join('');
ffmpeg.FS('writeFile', name + '.mp4', await fetchFile(video));
await ffmpeg.run(
'-i',
name + '.mp4',
'-f',
'gif',
name + '.gif',
);
const data = ffmpeg.FS('readFile', name + '.gif');
const url = URL.createObjectURL(
new Blob([data.buffer], { type: 'image/gif' }),
);
setGifs((gifs) => [...gifs, url]);
};
const convertToGif = async () => {
videos.forEach((video) => {
batchConvert(video);
}
);
return ready ? (
<div className="App">
{videos &&
videos.map((video) => (
<video controls width="250" src={URL.createObjectURL(video)}></video>
))}
<input type="file" multiple onChange={onInputChange} />
{videos && <button onClick={convertToGif}>Convert to Gif</button>}
{gifs && (
<div>
<h3>Result</h3>
{gifs.map((gif) => (
<img src={gif} width="250" />
))}
</div>
)}
</div>
) : (
<p>Loading...</p>
);
}
export default App;
The error I am getting is along the lines of "Cannot run multiple instances of FFmpeg at once", which I understand, however, I have no idea how to make the batchConvert function only run one instance at a time, whether it's outside or inside the function.
Thank you!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…