{"id":28046,"date":"2022-07-22T11:37:27","date_gmt":"2022-07-22T11:37:27","guid":{"rendered":"http:\/\/video-to-gif-converter-with-react"},"modified":"2023-08-30T03:58:19","modified_gmt":"2023-08-30T10:58:19","slug":"video-to-gif-converter-with-react","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/","title":{"rendered":"Video to GIF Converter with React"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Sometimes we make videos but want them as an image, or sometimes we make videos but are obliged to upload images instead. The solution to this is converting the video to GIF (Graphics Interchange Format).  <a href=\"https:\/\/cloudinary.com\/glossary\/interlaced-gif\">GIF<\/a> is a lossless format for image files that supports both animated and static images.\nIn this tutorial, we will be showing how to convert a video into an GIF with React.<\/p>\n<h2>Prerequisites<\/h2>\n<p>To follow this tutorial, you need the following pre-requisites:<\/p>\n<ul>\n<li>Basic knowledge of JavaScript.<\/li>\n<li>Understanding of Reactjs.<\/li>\n<\/ul>\n<p>The complete code is here on <a href=\"https:\/\/codesandbox.io\/embed\/cranky-ptolemy-rggwtt?autoresize=1&amp;fontsize=14&amp;hidenavigation=1&amp;theme=dark\">Codesandbox<\/a>.<\/p>\n<p><a href=\"https:\/\/codesandbox.io\/embed\/cranky-ptolemy-rggwtt?autoresize=1&amp;fontsize=14&amp;hidenavigation=1&amp;theme=dark\">https:\/\/codesandbox.io\/embed\/cranky-ptolemy-rggwtt?autoresize=1&amp;fontsize=14&amp;hidenavigation=1&amp;theme=dark<\/a><\/p>\n<h2>Getting Started<\/h2>\n<p>Firstly, setup a react app. To do so, paste the command below; ensure you have npm and node installed.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npx create-react-app video-to-gif\n<\/code><\/span><\/pre>\n<p>Next is to run the application; run the command below to run the app.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm start\n<\/code><\/span><\/pre>\n<p>Navigate to your browser on localhost:3000, and you should have the default react page displayed.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_8AD1CC1B64B6708C02A985F4EE6968CFA4B17ED4A94147E9861A3C160C8A484F_1654599435746_nee+2.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"996\"\/><\/p>\n<h2>Installing Packages<\/h2>\n<p>Now that react is set up, navigate to your terminal and run the command below to install the packages used in converting and downloading the video to gif.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-keyword\">@ffmpeg<\/span>\/ffmpeg<span class=\"hljs-keyword\">@0<\/span>.9.8 @ffmpeg\/core@<span class=\"hljs-number\">0.9<\/span>.<span class=\"hljs-number\">0<\/span> file-saver\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Ensure you install these specific versions of <code>@ffmpeg\/ffmpeg<\/code> and <code>@ffmpeg\/core<\/code> as the latest versions has issues we won\u2019t deal with in this tutorial.<\/p>\n<h2>Implementing the Video to GIF converter<\/h2>\n<p>Next is to make changes to <code>App.js<\/code> file. Open the file and add the code snippet below.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/App.js<\/span>\n<span class=\"hljs-keyword\">import<\/span> React, { useEffect,useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'.\/App.css'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { createFFmpeg, fetchFile } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@ffmpeg\/ffmpeg\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { saveAs } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"file-saver\"<\/span>;\n    \n<span class=\"hljs-keyword\">const<\/span> ffmpeg = createFFmpeg({ <span class=\"hljs-attr\">log<\/span>: <span class=\"hljs-literal\">true<\/span> });\n    \n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> &#91;video, setVideo] = useState();\n  <span class=\"hljs-keyword\">const<\/span> &#91;name, setName] = useState()\n      \n  <span class=\"hljs-keyword\">const<\/span> init= <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n    <span class=\"hljs-keyword\">await<\/span> ffmpeg.load();\n  };\n  <span class=\"hljs-keyword\">const<\/span> setvid = <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>)=&gt;<\/span>{\n    setVideo(e.target.files?.item(<span class=\"hljs-number\">0<\/span>))\n    setName(e.target.files&#91;<span class=\"hljs-number\">0<\/span>].name)\n  }\nuseEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    init();\n}, &#91;]);\n\n<span class=\"hljs-keyword\">return<\/span> (\n  <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"App\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"App-header\"<\/span>&gt;<\/span>\n      {video &amp;&amp; (\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">controls<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"250\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{URL.createObjectURL(video)}<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">video<\/span>&gt;<\/span>\n      )}\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{(e)<\/span>=&gt;<\/span>setvid(e)}\/&gt;\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n)\n}\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We first declare the <code>ffmpeg<\/code> using the <code>createffmpeg<\/code> method and set the log to true to allow us to log the processes. We then make use of the following :<\/p>\n<ul>\n<li>\n<p><strong>useEffect<\/strong> ****to call the <code>init()<\/code>, which loads the <code>ffmpeg<\/code> using the <code>FF``mpeg.load()<\/code> function.<\/p>\n<\/li>\n<li>\n<p>the <strong>onChange<\/strong> event handler is triggered when you select the video to convert. It also triggers the <code>setvid()<\/code>, which sets the state for the name of the file and sets the video to be rendered within the return method.<\/p>\n<\/li>\n<\/ul>\n<p><strong>Note:<\/strong> sometimes, we might run into an error \u201c<strong>S****haredArrayBufffer<\/strong> is not defined\u201d don\u2019t panic, as this is due to SharedArrayBuffer being only available to pages that are <a href=\"https:\/\/developer.chrome.com\/blog\/enabling-shared-array-buffer\/#cross-origin-isolation\">cross-origin isolated<\/a>.<\/p>\n<p>To fix that, click the link below.<\/p>\n<p><a href=\"https:\/\/github.com\/gzuidhof\/coi-serviceworker\">https:\/\/github.com\/gzuidhof\/coi-serviceworker<\/a><\/p>\n<ul>\n<li>Download <code>coi-serviceworker.js<\/code> (or <code>coi-serviceworker.min.js<\/code>).<\/li>\n<li>Put it in the public folder<\/li>\n<li>Add this to the <code>index.html<\/code> file:<\/li>\n<\/ul>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"coi-serviceworker.min.js\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Save and  start the app server with <code>npm run start<\/code> . You should get something like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_F4A89638957BBB43E4EC7E9EBD76F0993E88E7D379E8C5830F2843FC152DCEAD_1656999556890_Screenshot+2022-07-05+at+06.37.37.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"1104\"\/><\/p>\n<p>Click on the <strong>Choose file<\/strong> button and upload a video. You should get something like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_8AD1CC1B64B6708C02A985F4EE6968CFA4B17ED4A94147E9861A3C160C8A484F_1654613719811_image.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1920\" height=\"908\"\/><\/p>\n<p>Now that the video is rendered let\u2019s update the <code>App.js<\/code> file with the conversion functionality.<\/p>\n<p>First, add this <code>button<\/code> below <code>header<\/code> . The button will trigger the function that converts the video to a gif<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/App.js<\/span>\n...\nconst init = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n  <span class=\"hljs-keyword\">await<\/span> ffmpeg.load();\n};\n\n<span class=\"hljs-keyword\">const<\/span> convertToGif = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n  <span class=\"hljs-keyword\">await<\/span> ffmpeg.FS(<span class=\"hljs-string\">'writeFile'<\/span>, name, <span class=\"hljs-keyword\">await<\/span> fetchFile(video));\n  <span class=\"hljs-keyword\">await<\/span> ffmpeg.run(<span class=\"hljs-string\">'-i'<\/span>, name, <span class=\"hljs-string\">'-t'<\/span>, <span class=\"hljs-string\">'2.5'<\/span>, <span class=\"hljs-string\">'-ss'<\/span>, <span class=\"hljs-string\">'2.0'<\/span>, <span class=\"hljs-string\">'-f'<\/span>, <span class=\"hljs-string\">'gif'<\/span>, <span class=\"hljs-string\">'output.gif'<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> data =   ffmpeg.FS(<span class=\"hljs-string\">'readFile'<\/span>, <span class=\"hljs-string\">'output.gif'<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> url = URL.createObjectURL(\n    <span class=\"hljs-keyword\">new<\/span> Blob(&#91;data.buffer], { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">'image\/gif'<\/span> }),\n  );\n  saveAs(url, <span class=\"hljs-string\">\"output.gif\"<\/span>);\n};\n    ...\nreturn(\n  <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span>&gt;<\/span> \n    ...\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span><\/span>\n  <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{convertToGif}<\/span>&gt;<\/span>Download and Convert to GIF<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><\/span>\n     ...\n)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Let\u2019s break the code snippet above into chunks.<\/p>\n<p><code>**convertToGif()**<\/code>: this function is triggered after uploading the video. It allows you to download the converted file. Let\u2019s go through some of the methods in this function.<\/p>\n<p>One thing to keep in mind is the use of Web Assembly, which is what the package is built on.<\/p>\n<p><code>**FFmpeg.FS**<\/code><strong>:<\/strong> Web Assembly always handles its memory, and in other to run <code>FFmpeg<\/code>, we need to make it known to that file system by writing the file to the memory of the <code>FFmpeg<\/code>. This is what this function does. It accepts the video as parameter and saves it in temporary memory.<\/p>\n<p><strong>N\/B<\/strong>**:** <strong>I<\/strong>t only stays in memory until the browser is refreshed<\/p>\n<p>Next, is  the <code>FFmpeg.run()<\/code> function. We pass the following parameters:<\/p>\n<ul>\n<li>\n<code>**-i**<\/code><strong>:<\/strong> is the input file<\/li>\n<li>\n<code>**-t**<\/code><strong>:<\/strong> is the time or length of the video<\/li>\n<li>\n<code>**-ss**<\/code><strong>:<\/strong> is the starting second<\/li>\n<li>\n<code>**-f**<\/code><strong>:<\/strong> is for encoding, in our case, gif<\/li>\n<li>\n<code>**output.gif**<\/code>: is the name of the file we want to write to.<\/li>\n<\/ul>\n<p>Once this is complete, it saves the file in memory;<\/p>\n<p>Next, is to read the file by using the <code>FFmpeg.Fs(readFile,``&quot;<\/code> <code>the file in memory``&quot;``)<\/code><\/p>\n<p>After that, we need to convert the file to a URL for our file-saver package to be able to make it downloadable. To do that we use the blob method.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> url = URL.createObjectURL(\n  <span class=\"hljs-keyword\">new<\/span> Blob(&#91;data.buffer], { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">'image\/gif'<\/span> }),\n);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And lastly, we pass the URL to the file-saver and specify the download name.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">saveAs(url, <span class=\"hljs-string\">\"output.gif\"<\/span>);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Now we should have our <code>A``pp.j``s<\/code> file like the one below.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'.\/App.css'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { createFFmpeg, fetchFile } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@ffmpeg\/ffmpeg\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { saveAs } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"file-saver\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> ffmpeg = createFFmpeg({ <span class=\"hljs-attr\">log<\/span>: <span class=\"hljs-literal\">true<\/span> });\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> &#91;video, setVideo] = useState();\n  <span class=\"hljs-keyword\">const<\/span> &#91;name, setName] = useState()\n  <span class=\"hljs-keyword\">const<\/span> init = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n    <span class=\"hljs-keyword\">await<\/span> ffmpeg.load();\n  };\n  \n  <span class=\"hljs-keyword\">const<\/span> setVid = <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>) =&gt;<\/span> {\n    setVideo(e.target.files?.item(<span class=\"hljs-number\">0<\/span>))\n    setName(e.target.files&#91;<span class=\"hljs-number\">0<\/span>].name)\n  }\n\n  <span class=\"hljs-keyword\">const<\/span> convertToGif = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n    <span class=\"hljs-keyword\">await<\/span> ffmpeg.FS(<span class=\"hljs-string\">'writeFile'<\/span>, name, <span class=\"hljs-keyword\">await<\/span> fetchFile(video));\n    <span class=\"hljs-keyword\">await<\/span> ffmpeg.run(<span class=\"hljs-string\">'-i'<\/span>, name, <span class=\"hljs-string\">'-t'<\/span>, <span class=\"hljs-string\">'2.5'<\/span>, <span class=\"hljs-string\">'-ss'<\/span>, <span class=\"hljs-string\">'2.0'<\/span>, <span class=\"hljs-string\">'-f'<\/span>, <span class=\"hljs-string\">'gif'<\/span>, <span class=\"hljs-string\">'output.gif'<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> data = ffmpeg.FS(<span class=\"hljs-string\">'readFile'<\/span>, <span class=\"hljs-string\">'output.gif'<\/span>);\n    <span class=\"hljs-keyword\">const<\/span> url = URL.createObjectURL(\n      <span class=\"hljs-keyword\">new<\/span> Blob(&#91;data.buffer], { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">'image\/gif'<\/span> }),\n    );\n    saveAs(url, <span class=\"hljs-string\">\"output.gif\"<\/span>);\n  };\n  \nuseEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  init();\n}, &#91;]);\n\n<span class=\"hljs-keyword\">return<\/span> (\n  <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"App\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"App-header\"<\/span>&gt;<\/span>\n      {video &amp;&amp; (\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">controls<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"250\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{URL.createObjectURL(video)}<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">video<\/span>&gt;<\/span>\n      )}\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{(e)<\/span> =&gt;<\/span> setVid(e)} \/&gt;\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{convertToGif}<\/span>&gt;<\/span>Download and Convert to GIF<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n)\n}\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_8AD1CC1B64B6708C02A985F4EE6968CFA4B17ED4A94147E9861A3C160C8A484F_1657011652001_Animation345.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1901\" height=\"930\"\/><\/p>\n<h2>Conclusion<\/h2>\n<p>In this tutorial, we implemented conversion of videos to GIFs with React, and <code>ffmpeg.wasm<\/code> JavaScirpt wrappers <code>@ffmpeg\/ffmpeg<\/code> and <code>@ffmpeg\/core<\/code>.<\/p>\n<h2>Further Reading<\/h2>\n<p><a href=\"https:\/\/www.npmjs.com\/package\/@ffmpeg\/ffmpeg\">FFmpeg<\/a>\n<a href=\"https:\/\/www.npmjs.com\/package\/file-saver\">File-saver<\/a><\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28047,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[398,134,177,246,371,303],"class_list":["post-28046","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-ffmpeg","tag-guest-post","tag-javascript","tag-react","tag-under-review","tag-video"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Video to GIF Converter with React<\/title>\n<meta name=\"description\" content=\"In this tutorial, we will be showing how to convert a video into an GIF with React.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Video to GIF Converter with React\" \/>\n<meta property=\"og:description\" content=\"In this tutorial, we will be showing how to convert a video into an GIF with React.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-22T11:37:27+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-08-30T10:58:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"757\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Video to GIF Converter with React\",\"datePublished\":\"2022-07-22T11:37:27+00:00\",\"dateModified\":\"2023-08-30T10:58:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA\",\"keywords\":[\"ffmpeg\",\"Guest Post\",\"Javascript\",\"React\",\"Under Review\",\"Video\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\",\"name\":\"Video to GIF Converter with React\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA\",\"datePublished\":\"2022-07-22T11:37:27+00:00\",\"dateModified\":\"2023-08-30T10:58:19+00:00\",\"description\":\"In this tutorial, we will be showing how to convert a video into an GIF with React.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA\",\"width\":1600,\"height\":757},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Video to GIF Converter with React\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Video to GIF Converter with React","description":"In this tutorial, we will be showing how to convert a video into an GIF with React.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/","og_locale":"en_US","og_type":"article","og_title":"Video to GIF Converter with React","og_description":"In this tutorial, we will be showing how to convert a video into an GIF with React.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-07-22T11:37:27+00:00","article_modified_time":"2023-08-30T10:58:19+00:00","og_image":[{"width":1600,"height":757,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/"},"author":{"name":"","@id":""},"headline":"Video to GIF Converter with React","datePublished":"2022-07-22T11:37:27+00:00","dateModified":"2023-08-30T10:58:19+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA","keywords":["ffmpeg","Guest Post","Javascript","React","Under Review","Video"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/","name":"Video to GIF Converter with React","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA","datePublished":"2022-07-22T11:37:27+00:00","dateModified":"2023-08-30T10:58:19+00:00","description":"In this tutorial, we will be showing how to convert a video into an GIF with React.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA","width":1600,"height":757},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-to-gif-converter-with-react\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Video to GIF Converter with React"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925568\/Web_Assets\/blog\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533\/2eaea9fae686a8d8d3d0a7c544c3a317519c3f67-1600x757-1_28047bf533.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28046","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28046"}],"version-history":[{"count":2,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28046\/revisions"}],"predecessor-version":[{"id":31064,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28046\/revisions\/31064"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28047"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28046"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28046"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28046"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}