Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
489 views
in Technique[技术] by (71.8m points)

node.js - Running ffmpeg (WASM/NodeJS) on multiple input files in a React App

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!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...