'Error using FFmpeg.wasm for audio files in react: "ffmpeg.FS('readFile', 'output.mp3') error. Check if the path exists"
I'm currently building a browser-based audio editor and I'm using ffmpeg.wasm (a pure WebAssembly/JavaScript port of FFmpeg) to do it.
I'm using this excellent example, which allows you to uploaded video file and convert it into a gif:
import React, { useState, useEffect } from 'react';
import './App.css';
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
const ffmpeg = createFFmpeg({ log: true });
function App() {
  const [ready, setReady] = useState(false);
  const [video, setVideo] = useState();
  const [gif, setGif] = useState();
  const load = async () => {
    await ffmpeg.load();
    setReady(true);
  }
  useEffect(() => {
    load();
  }, [])
  const convertToGif = async () => {
    // Write the file to memory 
    ffmpeg.FS('writeFile', 'test.mp4', await fetchFile(video));
    // Run the FFMpeg command
    await ffmpeg.run('-i', 'test.mp4', '-t', '2.5', '-ss', '2.0', '-f', 'gif', 'out.gif');
    // Read the result
    const data = ffmpeg.FS('readFile', 'out.gif');
    // Create a URL
    const url = URL.createObjectURL(new Blob([data.buffer], { type: 'image/gif' }));
    setGif(url)
  }
  return ready ? (
    
    <div className="App">
      { video && <video
        controls
        width="250"
        src={URL.createObjectURL(video)}>
      </video>}
      <input type="file" onChange={(e) => setVideo(e.target.files?.item(0))} />
      <h3>Result</h3>
      <button onClick={convertToGif}>Convert</button>
      { gif && <img src={gif} width="250" />}
    </div>
  )
    :
    (
      <p>Loading...</p>
    );
}
export default App;
I've modified the above code to take an mp3 file recorded in the browser (recorded using the npm package 'mic-recorder-to-mp3' and passed to this component as a blobURL in the global state) and do something to it using ffmpeg.wasm:
import React, { useContext, useState, useEffect } from 'react';
import Context from '../../store/Context';
import Toolbar from '../Toolbar/Toolbar';
import AudioTranscript from './AudioTranscript';
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';
//Create ffmpeg instance and set 'log' to true so we can see everything
//it does in the console
const ffmpeg = createFFmpeg({ log: true });
const AudioEditor = () => {
    //Setup Global State and get most recent recording
    const { globalState } = useContext(Context);
    const { blobURL } = globalState;
    //ready flag for when ffmpeg is loaded
    const [ready, setReady] = useState(false);
    const [outputFileURL, setOutputFileURL] = useState('');
    //Load FFmpeg asynchronously and set ready when it's ready
    const load = async () => {
        await ffmpeg.load();
        setReady(true);
    }
    //Use UseEffect to run the 'load' function on mount
    useEffect(() => {
        load();
    }, []);
    const ffmpegTest = async () => {
        //must first write file to memory as test.mp3
        ffmpeg.FS('writeFile', 'test.mp3', await fetchFile(blobURL));
        //Run the FFmpeg command
        //in this case, trim file size down to 1.5s and save to memory as output.mp3
        ffmpeg.run('-i', 'test.mp3', '-t', '1.5', 'output.mp3');
        //Read the result from memory
        const data = ffmpeg.FS('readFile', 'output.mp3');
        //Create URL so it can be used in the browser
        const url = URL.createObjectURL(new Blob([data.buffer], { type: 'audio/mp3' }));
        setOutputFileURL(url);
    }
    return ready ? ( 
        <div>
            <AudioTranscript />
            <Toolbar />
            <button onClick={ffmpegTest}>
                Edit
            </button>
            {outputFileURL && 
                <audio
                    controls="controls"
                    src={outputFileURL || ""}
                />
            }
        </div>
    ) : (
        <div>
            Loading...
        </div>
    )
}
export default AudioEditor;
This code returns the following error when I press the edit button to call the ffmpegTest function:

I've experimented, and when I tweak the culprit line of code to:
const data = ffmpeg.FS('readFile', 'test.mp3');
the function runs without error, simply returning the input file. So I assume there must be something wrong with ffmpeg.run() line not storing 'output.mp3' in memory perhaps? I can't for the life of me figure out what's going on...any help would be appreciated!
Solution 1:[1]
Fixed it...
Turns out I needed to put an 'await' before ffmpeg.run(). Without that statement, the next line:
const data = ffmpeg.FS('readFile', 'output.mp3');
runs before output.mp3 is produced and stored in memory.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Rayhan Memon | 
