我最近遵循了 Fireship.io 的教程,制作了一个 React 应用程序,使用户能够输入视频文件并将其转换为 gif。这是来源 GitHub Repo。
该项目使用的软件包是
@ffmpeg/ffmpeg
和 @ffmpeg/core
,它们负责将视频转换为 GIF(尽管可以更改为任何内容,例如 FFmpeg CLI 工具)。
我想更进一步,让我可以一次转换多个视频,每个视频都转换成自己单独的 gif,但是,当第一个任务完成后,我在运行下一个任务时遇到了麻烦。
这里是文档我找到了关于ffmpeg wasm包。我还阅读了包提供商提供的这个example,以从单个文件中获得多个输出。
这是我的代码(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;
我收到的错误类似于“无法同时运行 FFmpeg 的多个实例”,我理解这一点,但是,我不知道如何使batchConvert 函数一次只运行一个实例,无论是在外部还是在外部在函数内部。
谢谢!
我认为你需要将
async/await
放入 forEach
const convertToGif = async () => {
videos.forEach(async (video) => {
await batchConvert(video);
}
);