๐ Supercharge Your Web Videos: MP4 to WebM Compression with React
Ever bored with nothing interesting at work? Well, thatโs when I decided to scratch my itch to tinker around with the current state of browser APIs. Could we compress videos directly through web APIs? In this blog, Iโll show you how to use modern browser features to compress MP4 videos to WebM formatโall within a React app.
๐ ๏ธ What You'll Need
Before we dive in, make sure you've got:
- React with Typescript
- Ant Design to build some nice UI.
Quick setup:
npm install antd
Setting up the component
Let's set up our React component with all the React imports:
import { useState, useRef, useEffect, ChangeEvent } from "react";
import { Button, Progress, message, Flex } from "antd";
const VideoCompression = () => {
const [sourceVideo, setSourceVideo] = useState<File | null>(null);
const [compressedVideo, setCompressedVideo] = useState<Blob | null>(null);
const [isCompressing, setIsCompressing] = useState(false);
const [progress, setProgress] = useState(0);
const [width, setWidth] = useState<string>("");
const [height, setHeight] = useState<string>("");
const videoRef = useRef<HTMLVideoElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
Accepting the File Upload
We need a way to choose our MP4 file:
const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {
if (!event.target.files) return;
const file = event.target.files[0];
if (file && file.type.startsWith("video/")) {
setSourceVideo(file);
setCompressedVideo(null);
} else {
message.error("Please select a valid video file.");
}
};
Extracting Video Metadata
Let's get the video metadata:
useEffect(() => {
if (sourceVideo) {
const video = document.createElement("video");
video.onloadedmetadata = () => {
setWidth(video.videoWidth.toString());
setHeight(video.videoHeight.toString());
};
video.src = URL.createObjectURL(sourceVideo);
}
}, [sourceVideo]);
Video Compression
Here's where the magic happens:
const compressVideo = async () => {
if (!sourceVideo) {
message.error("Please upload a video first.");
return;
}
setIsCompressing(true);
setProgress(0);
try {
const stream = videoRef.current?.captureStream();
const mediaRecorder = new MediaRecorder(stream, {
mimeType: "video/webm",
videoBitsPerSecond: 1000000,
});
const chunks: BlobPart[] = [];
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
chunks.push(event.data);
}
};
mediaRecorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
setCompressedVideo(blob);
setIsCompressing(false);
setProgress(100);
};
if (!videoRef.current) return;
videoRef.current.onloadedmetadata = () => {
videoRef.current!.muted = true;
videoRef.current?.play();
mediaRecorder.start();
};
videoRef.current.onended = () => {
mediaRecorder.stop();
videoRef.current?.pause();
};
videoRef.current.ontimeupdate = () => {
if (!videoRef.current) return;
const progress =
(videoRef.current.currentTime / videoRef.current.duration) * 100;
setProgress(progress);
};
if (!videoRef.current) return;
videoRef.current.width = Number.parseFloat(width);
videoRef.current.height = Number.parseFloat(height);
videoRef.current.src = URL.createObjectURL(sourceVideo);
} catch (err) {
message.error("Error compressing video: " + (err as Error).message);
setIsCompressing(false);
}
};
Downloading the Compressed Video
const downloadCompressedVideo = () => {
if (compressedVideo) {
const url = URL.createObjectURL(compressedVideo);
const a = document.createElement("a");
a.href = url;
a.download = "compressed_video.webm";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
};
๐ Launch Time: Putting It All Together
Here's a sneak peek of our complete work:
Deployment Link:
https://abhirup-99.github.io/browser-compression-webm/
Code Link:
https://github.com/Abhirup-99/browser-compression-webm
๐ Wrap-up: You're Now a Video Compression Wizard!
Congratulations! You've just built a powerful MP4 to WebM video compressor using React. Your web videos will now load faster than ever, delighting users and boosting your site's performance.
๐ Next Steps:
- I will be tinkering with the browser compression APIs further and hopefully there will be an blog out soon.
Top comments (0)