Home > Web Front-end > JS Tutorial > Compressing videos to webm in the browser

Compressing videos to webm in the browser

Mary-Kate Olsen
Release: 2024-10-06 06:22:02
Original
1146 people have browsed it

? 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:


<p>npm install antd</p>

Copy after login




Setting up the component

Let's set up our React component with all the React imports:


<p>import { useState, useRef, useEffect, ChangeEvent } from "react";<br>
import { Button, Progress, message, Flex } from "antd";</p>

<p>const VideoCompression = () => {<br>
  const [sourceVideo, setSourceVideo] = useState<File | null>(null);<br>
  const [compressedVideo, setCompressedVideo] = useState<Blob | null>(null);<br>
  const [isCompressing, setIsCompressing] = useState(false);<br>
  const [progress, setProgress] = useState(0);<br>
  const [width, setWidth] = useState<string>("");<br>
  const [height, setHeight] = useState<string>("");<br>
  const videoRef = useRef<HTMLVideoElement>(null);<br>
  const inputRef = useRef<HTMLInputElement>(null);</p>

Copy after login




Accepting the File Upload

We need a way to choose our MP4 file:


<p>const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {<br>
  if (!event.target.files) return;<br>
  const file = event.target.files[0];<br>
  if (file && file.type.startsWith("video/")) {<br>
    setSourceVideo(file);<br>
    setCompressedVideo(null);<br>
  } else {<br>
    message.error("Please select a valid video file.");<br>
  }<br>
};</p>

Copy after login




Extracting Video Metadata

Let's get the video metadata:


<p>useEffect(() => {<br>
  if (sourceVideo) {<br>
    const video = document.createElement("video");<br>
    video.onloadedmetadata = () => {<br>
      setWidth(video.videoWidth.toString());<br>
      setHeight(video.videoHeight.toString());<br>
    };<br>
    video.src = URL.createObjectURL(sourceVideo);<br>
  }<br>
}, [sourceVideo]);</p>

Copy after login




Video Compression

Here's where the magic happens:


<p>const compressVideo = async () => {<br>
    if (!sourceVideo) {<br>
      message.error("Please upload a video first.");<br>
      return;<br>
    }<br>
    setIsCompressing(true);<br>
    setProgress(0);<br>
    try {<br>
      const stream = videoRef.current?.captureStream();<br>
      const mediaRecorder = new MediaRecorder(stream, {<br>
        mimeType: "video/webm",<br>
        videoBitsPerSecond: 1000000,<br>
      });<br>
      const chunks: BlobPart[] = [];<br>
      mediaRecorder.ondataavailable = (event) => {<br>
        if (event.data.size > 0) {<br>
          chunks.push(event.data);<br>
        }<br>
      };<br>
      mediaRecorder.onstop = () => {<br>
        const blob = new Blob(chunks, { type: "video/webm" });<br>
        setCompressedVideo(blob);<br>
        setIsCompressing(false);<br>
        setProgress(100);<br>
      };<br>
      if (!videoRef.current) return;<br>
      videoRef.current.onloadedmetadata = () => {<br>
        videoRef.current!.muted = true;<br>
        videoRef.current?.play();<br>
        mediaRecorder.start();<br>
      };<br>
      videoRef.current.onended = () => {<br>
        mediaRecorder.stop();<br>
        videoRef.current?.pause();<br>
      };<br>
      videoRef.current.ontimeupdate = () => {<br>
        if (!videoRef.current) return;<br>
        const progress =<br>
          (videoRef.current.currentTime / videoRef.current.duration) * 100;<br>
        setProgress(progress);<br>
      };<br>
      if (!videoRef.current) return;<br>
      videoRef.current.width = Number.parseFloat(width);<br>
      videoRef.current.height = Number.parseFloat(height);<br>
      videoRef.current.src = URL.createObjectURL(sourceVideo);<br>
    } catch (err) {<br>
      message.error("Error compressing video: " + (err as Error).message);<br>
      setIsCompressing(false);<br>
    }<br>
  };</p>

Copy after login




Downloading the Compressed Video



<p>const downloadCompressedVideo = () => {<br>
  if (compressedVideo) {<br>
    const url = URL.createObjectURL(compressedVideo);<br>
    const a = document.createElement("a");<br>
    a.href = url;<br>
    a.download = "compressed_video.webm";<br>
    document.body.appendChild(a);<br>
    a.click();<br>
    document.body.removeChild(a);<br>
    URL.revokeObjectURL(url);<br>
  }<br>
};</p>

Copy after login




? Launch Time: Putting It All Together

Here's a sneak peek of our complete work:

Compressing videos to webm in the browser

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.

The above is the detailed content of Compressing videos to webm in the browser. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template