Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • React Tutorial
  • React Exercise
  • React Basic Concepts
  • React Components
  • React Props
  • React Hooks
  • React Router
  • React Advanced
  • React Examples
  • React Interview Questions
  • React Projects
  • Next.js Tutorial
  • React Bootstrap
  • React Material UI
  • React Ant Design
  • React Desktop
  • React Rebass
  • React Blueprint
  • JavaScript
  • Web Technology
Open In App
Next Article:
Create a Form using React JS
Next article icon

Create a Video Editor using React

Last Updated : 24 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Video Editor is one of the useful apps in day-to-day life. In this article, we’ll walk you through the process of building a basic video editing app using React Native. The application enables users to upload, trim, and convert specific scenes to GIFs and then download the final edited file directly from their browser.

Output Preview: Let us have a look at how the final output will look like.
Screenshot_85_1080x608

Prerequisites:

  • React
  • Node.js and npm
  • Ant Design UI libraries

Approach to create Video Editor

  1. We'll begin with setting up the project environment.
  2. To simplify, every component of the video editor is written and explained separately, such as: Video upload, Video player, Video editor, Video to GIF converter.
  3. Showcased how to use ffmpeg.wasm to launch an ffmpeg command that clips and converts the video to GIF in the browser.
  4. At last, all the components will be imported together in a VideoEditor.js and rendered in App.js file for the execution.

Functionalities of Video Editor:

  • Video import and playback.
  • Trim and cut video clips.
  • convert video to gif.
  • Preview and download edited video in real-time.

Steps to initialize a React project:

Step 1: Initialize a new Create React App React project called video-editor-wasm-react with the command below:

npx create-react-app video-editor-wasm-react
cd video-editor-wasm-react

Step 2: Create a file in src folder- setupProxy.js. This is required to enable SharedArrayBuffer in your browser so that it will make fmmpeg.wasm to function.

JavaScript
// src/setupProxy.js  module.exports = function (app) { 	app.use(function (req, res, next) { 		res.setHeader("Cross-Origin-Opener-Policy", "same-origin") 		res.setHeader("Cross-Origin-Embedder-Policy", "require-corp") 		next() 	}) } 


Step 3: Install the required dependencies.

npm install @ffmpeg/[email protected] antd video-react redux

Project Structure:

Screenshot-2024-02-02-180337

Dependencies:

"dependencies": {
"@ffmpeg/ffmpeg": "^0.10.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"antd": "^5.14.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"redux": "^5.0.1",
"video-react": "^0.16.0",
"web-vitals": "^2.1.4"
}

Example Code: Create the necessary files and add the following code.

CSS
/* App.css */  .App {     text-align: center; }  .App-logo {     height: 40vmin;     pointer-events: none; }  @media (prefers-reduced-motion: no-preference) {     .App-logo {         animation: App-logo-spin infinite 20s linear;     } }  .App-header {     background-color: #282c34;     min-height: 100vh;     display: flex;     flex-direction: column;     align-items: center;     justify-content: center;     font-size: calc(10px + 2vmin);     color: white; }  .App-link {     color: #61dafb; }  @keyframes App-logo-spin {     from {         transform: rotate(0deg);     }      to {         transform: rotate(360deg);     } } 
JavaScript
// src/components/VideoConversionButton.js  import { Button } from "antd" import { fetchFile } from "@ffmpeg/ffmpeg" import { sliderValueToVideoTime } from "../utils/utils"  function VideoConversionButton({ 	videoPlayerState, 	sliderValues, 	videoFile, 	ffmpeg, 	onConversionStart = () => { }, 	onConversionEnd = () => { }, 	onGifCreated = () => { }, }) { 	const convertToGif = async () => { 		// starting the conversion process 		onConversionStart(true)  		const inputFileName = "gif.mp4" 		const outputFileName = "output.gif"  		// writing the video file to memory 		ffmpeg.FS("writeFile", inputFileName, await fetchFile(videoFile))  		const [min, max] = sliderValues 		const minTime = sliderValueToVideoTime(videoPlayerState.duration, min) 		const maxTime = sliderValueToVideoTime(videoPlayerState.duration, max)  		// cutting the video and converting it to GIF with an FFMpeg command 		await ffmpeg 				.run("-i", inputFileName, "-ss", `${minTime}`,  						"-to", `${maxTime}`, "-f", "gif", outputFileName)  		// reading the resulting file 		const data = ffmpeg.FS("readFile", outputFileName)  		// converting the GIF file created by FFmpeg to a valid image URL 		const gifUrl = URL.createObjectURL(new Blob([data.buffer],  											{ type: "image/gif" })) 		onGifCreated(gifUrl)  		// ending the conversion process 		onConversionEnd(false) 	}  	return <Button onClick={() => convertToGif()}>Convert to GIF</Button> }  export default VideoConversionButton 
JavaScript
// src/components/VideoEditor.js  import { createFFmpeg } from "@ffmpeg/ffmpeg" import { useEffect, useState } from "react" import { Slider, Spin } from "antd" import { VideoPlayer } from "./VideoPlayer" import { sliderValueToVideoTime } from "../utils/utils" import VideoUpload from "./VideoUpload" import VideoConversionButton from "./VideoConversionButton" const ffmpeg = createFFmpeg({ log: true })  function VideoEditor() { 	const [ffmpegLoaded, setFFmpegLoaded] = useState(false) 	const [videoFile, setVideoFile] = useState() 	const [videoPlayerState, setVideoPlayerState] = useState() 	const [videoPlayer, setVideoPlayer] = useState() 	const [gifUrl, setGifUrl] = useState() 	const [sliderValues, setSliderValues] = useState([0, 100]) 	const [processing, setProcessing] = useState(false)  	useEffect(() => { 		// loading ffmpeg on startup 		ffmpeg.load().then(() => { 			setFFmpegLoaded(true) 		}) 	}, [])  	useEffect(() => { 		const min = sliderValues[0] 		// when the slider values are updated, updating the 		// video time 		if (min !== undefined && videoPlayerState && videoPlayer) { 			videoPlayer.seek(sliderValueToVideoTime( 				videoPlayerState.duration, min 			)) 		} 	}, [sliderValues])  	useEffect(() => { 		if (videoPlayer && videoPlayerState) { 			// allowing users to watch only the portion of 			// the video selected by the slider 			const [min, max] = sliderValues  			const minTime =sliderValueToVideoTime(videoPlayerState.duration,min) 			const maxTime =sliderValueToVideoTime(videoPlayerState.duration,max)  			if (videoPlayerState.currentTime < minTime) { 				videoPlayer.seek(minTime) 			} 			if (videoPlayerState.currentTime > maxTime) { 				// looping logic 				videoPlayer.seek(minTime) 			} 		} 	}, [videoPlayerState])  	useEffect(() => { 		// when the current videoFile is removed, 		// restoring the default state 		if (!videoFile) { 			setVideoPlayerState(undefined) 			setSliderValues([0, 100]) 			setVideoPlayerState(undefined) 			setGifUrl(undefined) 		} 	}, [videoFile])  	return ( 		<div> 			<Spin 				spinning={processing || !ffmpegLoaded} 				tip={!ffmpegLoaded ? "Waiting for FFmpeg to load..." 									:"Processing..."} 			> 				<div> 					{videoFile ? ( 						<VideoPlayer 							src={URL.createObjectURL(videoFile)} 							onPlayerChange={(videoPlayer) => { 								setVideoPlayer(videoPlayer) 							}} 							onChange={(videoPlayerState) => { 								setVideoPlayerState(videoPlayerState) 							}} 						/> 					) : ( 						<h1>Upload a video</h1> 					)} 				</div> 				<div className={"upload-div"}> 					<VideoUpload 						disabled={!!videoFile} 						onChange={(videoFile) => { 							setVideoFile(videoFile) 						}} 						onRemove={() => { 							setVideoFile(undefined) 						}} 					/> 				</div> 				<div className={"slider-div"}> 					<h3>Cut Video</h3> 					<Slider 						disabled={!videoPlayerState} 						value={sliderValues} 						range={true} 						onChange={(values) => { 							setSliderValues(values) 						}} 						tooltip={{ 							formatter: null, 						}} 					/> 				</div> 				<div className={"conversion-div"}> 					<VideoConversionButton 						onConversionStart={() => { 							setProcessing(true) 						}} 						onConversionEnd={() => { 							setProcessing(false) 						}} 						ffmpeg={ffmpeg} 						videoPlayerState={videoPlayerState} 						sliderValues={sliderValues} 						videoFile={videoFile} 						onGifCreated={(girUrl) => { 							setGifUrl(girUrl) 						}} 					/> 				</div> 				{gifUrl && ( 					<div className={"gif-div"}> 						<h3>Resulting GIF</h3> 						<img src={gifUrl}  							className={"gif"}  							alt={"GIF file generated in the client side"}/> 						<a href={gifUrl}  						download={"test.gif"}  						className={"ant-btn ant-btn-default"}> 							Download 						</a> 					</div> 				)} 			</Spin> 		</div> 	) }  export default VideoEditor 
JavaScript
// src/components/VideoPlayer.js  import { BigPlayButton, ControlBar,  		LoadingSpinner, Player, PlayToggle } from "video-react" import "video-react/dist/video-react.css" import { useEffect, useState } from "react"  export function VideoPlayer({ 	src, 	onPlayerChange = () => { }, 	onChange = () => { }, 	startTime = undefined, }) { 	const [player, setPlayer] = useState(undefined) 	const [playerState, setPlayerState] = useState(undefined)  	useEffect(() => { 		if (playerState) { 			onChange(playerState) 		} 	}, [playerState])  	useEffect(() => { 		onPlayerChange(player)  		if (player) { 			player.subscribeToStateChange(setPlayerState) 		} 	}, [player])  	return ( 		<div className={"video-player"}> 			<Player 				ref={(player) => { 					setPlayer(player) 				}} 				startTime={startTime} 			> 				<source src={src} /> 				<BigPlayButton position="center" /> 				<LoadingSpinner /> 				<ControlBar autoHide={false} disableDefaultControls={true}> 					<PlayToggle /> 				</ControlBar> 			</Player> 		</div> 	) } 
JavaScript
// src/components/VideoUpload.js  import { Button, Upload } from "antd"  function VideoUpload({ disabled, onChange = () => { }, onRemove = () => { } }) { 	return ( 		<> 			<Upload 				disabled={disabled} 				beforeUpload={() => { 					return false 				}} 				accept="video/*" 				onChange={(info) => { 					if (info.fileList && info.fileList.length > 0) { 						onChange(info.fileList[0].originFileObj) 					} 				}} 				showUploadList={false} 			> 				<Button>Upload Video</Button> 			</Upload> 			<Button 				danger={true} 				disabled={!disabled} 				onClick={() => { 					onRemove(undefined) 				}} 			> 				Remove 			</Button> 		</> 	) }  export default VideoUpload 
JavaScript
// src/utils/utils.js  export function sliderValueToVideoTime(duration, sliderValue) { 	return Math.round(duration * sliderValue / 100) } 
JavaScript
// App.js  import "./App.css" import VideoEditor from "./components/VideoEditor"  function App() { 	return ( 		<div className={"app"}> 			<VideoEditor /> 		</div> 	) }  export default App 


Step 4: To start the application run the following command.

npm start

Output:


Next Article
Create a Form using React JS
author
hadaa914
Improve
Article Tags :
  • Project
  • Web Technologies
  • ReactJS
  • Geeks Premier League
  • ReactJS-Projects
  • Geeks Premier League 2023

Similar Reads

  • Create a Video Streaming Platform with React
    This article focuses on Creating and Designing a Video Streaming Application using React JS. In this application, users can stream any video just by entering the video link in the input field, the preview and streaming of the video is started in the application itself. Proper error messages are show
    4 min read
  • Create a Video Player App using React-Native
    React-Native is an open-source JavaScript framework used to broaden cross-platform packages i.e., you may write code in React-Native and publish it as an Android or IOS app. In this article, we will build a Video Player app with the usage of React-Native. The app will run on both Android and IOS. Pr
    4 min read
  • Create a Form using React JS
    Creating a From in React includes the use of JSX elements to build interactive interfaces for user inputs. We will be using HTML elements to create different input fields and functional component with useState to manage states and handle inputs. Prerequisites:Functional ComponentsJavaScript ES6JSXPr
    5 min read
  • Create an Image/Video Gallery using React-Native
    An Image/Video Gallery is a common feature in mobile applications. This article will guide you for creating an Image/Video Gallery using React Native.We will learn to build an Image/Video Gallery app using React-Native. In this app, we will display the images and videos in the form of a grid, and on
    5 min read
  • Create a Voice Notes App using React-Native
    We are going to build a Voice Notes app that will allow us to save our voice as a recording in our application. It is similar to a notes app but we will have our voice as notes. We can play the voice recordings, record them, and delete them. It leverages React-Native's cross-platform capabilities to
    5 min read
  • Create a Text Editor App using React-Native
    In this article, we are going to implement a text editor app using React Native. It will contain multiple text formatting functionalities like bold, italic, underline, etc. We will implement Editor with a library called "react-native-pell-rich-editor." Preview of final output: Let us have a look at
    3 min read
  • Create a Video Streaming App using React-Native
    React-Native is an open-source JavaScript framework used to broaden cross-platform packages i.e., you may write code in React-Native and publish it as an Android or IOS app. In this article, we will build a Video Streaming app using React-Native. The app will run on both Android and IOS. Preview of
    4 min read
  • Create a Searchable Video List in React
    In ReactJS, we can embed the video previews as an important feature in the application. There are multiple videos with the exact similar names. To filter out the videos or to search the specific term video in the application, we can create a search video list. In this article, we will see how we can
    5 min read
  • Create a Snake Game in React
    Snake Game using ReactJS project implements functional components and manages the state accordingly. The developed Game allows users to control a snake using arrow keys or touch the buttons displayed on the screen to collect food and grow in length. The goal of the game is to eat as much food as pos
    7 min read
  • How to create a video to GIF converter using ReactJS ?
    When you think about a GIF image, a video is a must convert into a .gif format to an image. For this project, we are using FFMPEG library utility written in the C programming language. With the support of web Assembly, it can run in browsers easily without any need for a server, also here we are usi
    7 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences