useFFmpeg
is a custom React hook designed to facilitate loading and transcoding media files using ffmpeg.wasm. This hook provides an easy way to load the ffmpeg library, manage the loading state, and transcode media files into different formats, all from within a React application.
- Load FFmpeg: Load the FFmpeg library and prepare it for file transcoding.
- Transcode Files: Convert media files from one format to another using FFmpeg.
- File Format Support: Transcode a variety of video, audio, image, text, and document formats.
- MIME Types Object: Access the supported MIME types for file formats, making it easy to check which types are accepted for transcoding.
The useFFmpeg
hook supports a broad range of MIME types, focusing exclusively on media files for transcoding. Below are the supported formats:
-
mp4
:video/mp4
-
webm
:video/webm
-
mkv
:video/x-matroska
-
mov
:video/quicktime
-
avi
:video/x-msvideo
-
flv
:video/x-flv
-
ts
:video/MP2T
-
ogv
:video/ogg
-
asf
:video/x-ms-asf
-
3gp
:video/3gpp
-
rm
:application/vnd.rn-realmedia
-
mp3
:audio/mpeg
-
wav
:audio/x-wav
-
aac
:audio/aac
-
flac
:audio/flac
-
ogg
:audio/ogg
-
m4a
:audio/mp4
-
wma
:audio/x-ms-wma
-
amr
:audio/amr
-
opus
:audio/opus
-
png
:image/png
-
jpeg
/jpg
:image/jpeg
-
gif
:image/gif
-
svg
:image/svg+xml
-
webp
:image/webp
-
bmp
:image/bmp
-
tiff
:image/tiff
-
ico
:image/x-icon
To use the useFFmpeg
hook, you'll need to install it along with the @ffmpeg/utils
package, which is a necessary dependency for working with FFmpeg.
Install useFFmpeg
from npm:
npm install use-ffmpeg
Then, install the @ffmpeg/util package:
npm install @ffmpeg/util
npm install @ffmpeg/ffmpeg
o prevent common hook-related errors when using context providers in your React application, we provide an FFmpegContextProvider
. This is particularly useful when you have multiple context providers or complex component hierarchies in your app root.
import { FFmpegContextProvider } from "use-ffmpeg";
// Wrap your app with the FFmpegContextProvider
const App = () => {
return (
<FFmpegContextProvider>
<OtherContextProvider>
<YourApplication />
</OtherContextProvider>
</FFmpegContextProvider>
);
};
This setup prevents common issues like:
- Invalid hook calls
- Conflicts with other context providers
When using the context provider, you can still use the useFFmpeg hook normally in your components:
import { useFFmpeg } from "use-ffmpeg";
const YourComponent = () => {
const { loadFFmpeg, loaded, transcode } = useFFmpeg();
// Rest of your component code...
};
In addition to the core functionality, users also have access to a predefined object containing supported MIME types, which can be used directly in the application. This object allows easy reference to MIME types for transcoding operations.
You can access the object like this:
import { mimeTypes } from "use-ffmpeg";
// Example usage:
console.log(mimeTypes.video.mp4); // Output: 'video/mp4'
console.log(mimeTypes.audio.mp3); // Output: 'audio/mpeg'
This object contains the MIME types categorized for video, audio, image, text, and document formats. It helps simplify the process of referencing MIME types, especially when dealing with transcoding options.
By default, the useFFmpeg hook will load FFmpeg from a CDN (Content Delivery Network) that is automatically set. In this case, you don't need to specify a custom URL.
import { useFFmpeg } from "use-ffmpeg";
const MyComponent = () => {
const { loadFFmpeg, loaded, transcode } = useFFmpeg();
useEffect(() => {
loadFFmpeg(); // This will use the default FFmpeg URL.
}, []);
if (!loaded) {
return <div>Loading FFmpeg...</div>;
}
return <div>FFmpeg is ready!</div>;
};
If you wish to load FFmpeg from a custom URL, you can pass the URL as a parameter to loadFFmpeg. This can be useful if you are hosting your own FFmpeg build or need to use a specific version of the library.
import { useFFmpeg } from "use-ffmpeg";
const MyComponent = () => {
const { loadFFmpeg, loaded, transcode } = useFFmpeg();
useEffect(() => {
loadFFmpeg("https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm"); // Custom URL for FFmpeg.
}, []);
if (!loaded) {
return <div>Loading FFmpeg...</div>;
}
return <div>FFmpeg is ready!</div>;
};
To enable FFmpeg with multithreading, you need to set the mt: true option in the loadFFmpeg function. Multithreading support is available in a specific version of FFmpeg (version 0.12.6 and above), which is optimized for better performance on multicore systems.
import { useFFmpeg } from "use-ffmpeg";
const MyComponent = () => {
const { loadFFmpeg, loaded, transcode } = useFFmpeg();
useEffect(() => {
// Load FFmpeg with multithreading enabled
loadFFmpeg("https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm", true);
}, []);
if (!loaded) {
return <div>Loading FFmpeg with multithreading...</div>;
}
return <div>FFmpeg with multithreading is ready!</div>;
};
This will load the multithreaded version of FFmpeg. Please note that FFmpeg version 0.12.6 is the version that supports multithreading.
The current supported version for multithreaded FFmpeg is 0.12.6, available at: URL: https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm When using multithreading, make sure to use the correct version (@ffmpeg/core-mt) in the URL. The -mt indicates that the build supports multithreading. The mt: true option is required to enable multithreaded transcoding. For more information and the latest builds, you can visit the official FFmpeg WASM page.
If you are using Vite, make sure to use the ESM version of the URL for compatibility.
-
Incorrect URL (for non-Vite users): https://unpkg.com/@ffmpeg/core@0.12.10/dist/umd
-
Correct URL (for Vite users): https://unpkg.com/@ffmpeg/core@0.12.10/dist/esm
Caution:
If you are a Vite user, you should use the ESM version of FFmpeg to ensure compatibility.
Once FFmpeg is loaded, you can use the transcode function to convert a file to another format. The transcode function accepts the following parameters:
file: The file to be transcoded (e.g., a video or audio file). outputFileName: The desired name for the transcoded file. options (optional): An array of FFmpeg command options to customize the transcoding behavior. The transcode function returns an object containing two key values:
URL: A URL that references the transcoded file, which can be used to display or download the file. File Size: The human-readable file size of the transcoded file, such as 1.2 MB or 500 KB.
Here’s a basic example of how to use the transcode function. It converts a file to a specified output format and provides both the URL and file size for further use:
const handleFileUpload = async (file: File) => {
try {
const outputFileName = "output.mp4"; // Specify output file name
const { fileUrl, fileSize } = await transcode(file, outputFileName); // Transcode the file
// Now you can use the URL to download or display the transcoded file
console.log("Transcoded file URL:", fileUrl);
console.log("Transcoded file size:", fileSize);
// Example: Create a download link
const downloadLink = document.createElement("a");
downloadLink.href = fileUrl;
downloadLink.download = outputFileName;
downloadLink.innerText = `Download Transcoded File (${fileSize})`;
document.body.appendChild(downloadLink);
} catch (error) {
console.error("Error transcoding file:", error);
}
};
Transcoded File URL: This is a temporary URL that references the transcoded file as a blob. You can use this URL for displaying or downloading the file. Human-readable File Size: The file size is provided in a human-readable format, making it easier for users to understand the output size (e.g., 1.2 MB). This allows users to transcode files and easily work with the resulting transcoded content, whether for display, download, or further processing.
You can pass an array of strings with custom FFmpeg command options for more control over the transcoding process. For example, if you want to change the resolution of a video or apply specific audio settings, you can use the following command options.
Here is an example of an FFmpeg command that resizes a video to 1280x720 and converts it to the mp4 format:
ffmpeg -i input.mp4 -vf "scale=1280:720" -acodec aac -vcodec libx264 output.mp4
his command:
Takes input.mp4 as the input file (-i input.mp4). Applies a video filter to resize it to 1280x720 (-vf "scale=1280:720"). Sets the audio codec to aac (-acodec aac). Sets the video codec to libx264 (-vcodec libx264). Outputs the result to output.mp4.
You can pass this FFmpeg command as an array of options:
const handleFileUpload = async (file: File) => {
try {
const outputFileName = "output.mp4";
const options = [
"-vf",
"scale=1280:720", // Apply video resizing
"-acodec",
"aac", // Set audio codec to AAC
"-vcodec",
"libx264", // Set video codec to H.264
];
const transcodedFile = await transcode(file, outputFileName, options); // Transcode the file with custom options
// Do something with the transcoded file (e.g., download, display, etc.)
} catch (error) {
console.error("Error transcoding file:", error);
}
};
-
loadFFmpeg(baseUrl?: string, mt?: boolean): Promise<void>
- Purpose: Loads FFmpeg and sets it up for transcoding.
-
Parameters:
-
baseUrl
(optional): The URL to load FFmpeg from. -
mt
(optional): Boolean flag to enable multithreading.
-
-
transcode(file: File, outputFileFullName: string, cmdOptions?: string[]): Promise<Buffer>
- Purpose: Transcodes a file to a specified output format.
-
Parameters:
-
file
: The file to be transcoded. -
outputFileFullName
: The full name of the output file (including extension). -
cmdOptions
(optional): Custom FFmpeg command-line options for transcoding.
-
The hook includes basic error handling during FFmpeg loading and transcoding. If an error occurs, it's passed to a custom errorHandler function, which logs the error and provides feedback.
import { useFFmpeg } from "use-ffmpeg";
const VideoTranscoder = () => {
const { loadFFmpeg, loaded, transcode } = useFFmpeg();
const [file, setFile] = useState(null);
useEffect(() => {
loadFFmpeg(); // Default FFmpeg URL
}, []);
const handleFileChange = (e) => {
setFile(e.target.files[0]);
};
const handleTranscode = async () => {
if (file) {
try {
const outputFileName = "converted.mp4";
const transcodedData = await transcode(file, outputFileName);
// Do something with transcoded data, like saving or displaying it
} catch (error) {
console.error("Transcoding failed:", error);
}
}
};
if (!loaded) return <div>Loading FFmpeg...</div>;
return (
<div>
<input type="file" onChange={handleFileChange} />
<button onClick={handleTranscode}>Transcode</button>
</div>
);
};
Feel free to fork the repository, submit issues, and contribute improvements. If you want to suggest any new features or need help with the hook, please open an issue.
This package is open source and available under the MIT License.