{"id":63,"date":"2024-08-13T05:32:04","date_gmt":"2024-08-13T05:32:04","guid":{"rendered":"https:\/\/kylehayhurst.com\/?p=63"},"modified":"2024-09-08T01:53:47","modified_gmt":"2024-09-08T01:53:47","slug":"creating-gifs-from-video-with-ffmpeg","status":"publish","type":"post","link":"https:\/\/kylehayhurst.com\/?p=63","title":{"rendered":"Creating GIFs from Video with FFMPEG"},"content":{"rendered":"\n<p>I love reacting with GIFs, pretty much every chance I get. There&#8217;s a ton I still don&#8217;t understand about my brain, but I find it very easy to relate a situation to a clip from a show or movie I&#8217;ve watched.<\/p>\n\n\n\n<p>This leads me to search the internet for this very specific scene and I often can&#8217;t find it, or the quality is bad, maybe the text isn&#8217;t correct. This led me to figure out how to generate these myself.<\/p>\n\n\n\n<p>Years ago I had used ffmpeg to do this, and I was fine with continuing this approach since it felt less restrictive. There are a bunch of apps out there that can help you do this easily, but they may have length caps.<\/p>\n\n\n\n<p>I&#8217;ve broken this process into two scripts that run on Windows, batch files. This depends on ffmpeg being installed already and accessible from the command line. The first batch file will slice the video into a GIF, I&#8217;ve called it make_gif.bat:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">@echo off\nsetlocal\n\nREM Check if FFmpeg is installed\nwhere ffmpeg &gt;nul 2&gt;&amp;1\nif %errorlevel% neq 0 (\n    echo FFmpeg is not installed or not in PATH.\n    echo Please install FFmpeg and try again.\n    exit \/b\n)\n\nREM Check if enough parameters are provided\nif &quot;%~4&quot;==&quot;&quot; (\n    echo Usage: %0 input_video start_time end_time output_gif\n    exit \/b\n)\n\nREM Set input parameters\nset input_video=%1\nset start_time=%2\nset end_time=%3\nset output_gif=%4\n\nREM Create GIF from video snippet\nffmpeg -i &quot;%input_video%&quot; -ss %start_time% -to %end_time% -vf &quot;fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&quot; &quot;%output_gif%&quot;\n\necho GIF creation completed: %output_gif%<\/code><\/pre>\n\n\n\n<p>Here&#8217;s how I use this script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\\make_gif.bat {video filename} {start time} {end time} {output filename}<\/code><\/pre>\n\n\n\n<p>An example of the usage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\\make_gif.bat .\\somevideo.mkv 00:08:40.000 00:08:44.150 output.gif<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"180\" src=\"https:\/\/kylehayhurst.com\/wp-content\/uploads\/2024\/03\/forced_smile.gif\" alt=\"Terry, Scully, and Hitchcock forcing smiles\" class=\"wp-image-32\"\/><\/figure>\n\n\n\n<p>This is good enough for those GIFs that can stand on their own with no text. But I often like to include the text for those who don&#8217;t remember the scene as clearly.<\/p>\n\n\n\n<p>Create the following batch file by saving this to a .bat file type in Windows:<\/p>\n\n\n\n<pre class=\"wp-block-prismatic-blocks\"><code class=\"language-\">@echo off\n\nREM Check if FFmpeg is installed\nwhere ffmpeg &gt;nul 2&gt;&amp;1\nif %errorlevel% neq 0 (\n    echo FFmpeg is not installed or not in PATH.\n    echo Please install FFmpeg and try again.\n    exit \/b\n)\n\nREM Check if enough parameters are provided\nif &quot;%~5&quot;==&quot;&quot; (\n    echo Usage: %0 input_filename start_frame_number end_frame_number text_to_add output_filename [font_size]\n    exit \/b\n)\n\nREM Set script parameters\nset input_gif=%~1\nset start_frame=%~2\nset end_frame=%~3\nset text=%~4\nset output_gif=%~5\nset border_width=2\n\nif &quot;%~6&quot;==&quot;&quot; (\n    set font_size=24\n) else (\n    set font_size=%~6\n)\n\n\nREM Build and run ffmpeg command\nffmpeg -i %input_gif% -vf &quot;drawtext=fontfile=C\\\\:\/Windows\/fonts\/arial.ttf:text=&#039;%text%&#039;:fontcolor=white:bordercolor=black:borderw=%border_width%:fontsize=%font_size%:x=(w-text_w)\/2:enable=&#039;between(n,%start_frame%,%end_frame%)&#039;:y=h-th-5,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&quot; %output_gif%\n\nREM Check for errors\nif errorlevel 1 (\n  echo Error adding text to gif.\n  exit \/b 1\n)\n\necho Text added to gif successfully.\n<\/code><\/pre>\n\n\n\n<p>Here&#8217;s how the script is used:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\\add_text_to_gif.bat {input filename} {start frame number} {end frame number} {text added} {output filename} {font size, optional}<\/code><\/pre>\n\n\n\n<p>An example of the usage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\\add_text_to_gif.bat output.gif 0 20 &quot;GIF text goes here&quot; output2.gif 20<\/code><\/pre>\n\n\n\n<p>The frame numbers can be figured out by guessing around the length of the clip as well as the frames per second. I believe the GIFs are generated at 10 frames per second.<\/p>\n\n\n\n<p>It looks silly using the two output filenames but it flows nicely from the command line. I could just change the first output from making the GIF but that doesn&#8217;t seem right either.<\/p>\n\n\n\n<p>I hope others find this useful and we get many more GIFs on the internet.<\/p>\n\n\n\n<p>Feel free to leave some suggestions for improvements, or share a GIF you created!<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"320\" height=\"180\" src=\"https:\/\/kylehayhurst.com\/wp-content\/uploads\/2024\/01\/adrenaline.gif\" alt=\"Captain Holt reading a piece of paper while sitting behind his desk\" class=\"wp-image-21\"\/><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I love reacting with GIFs, pretty much every chance I get. There&#8217;s a ton I still don&#8217;t understand about my brain, but I find it very easy to relate a situation to a clip from a show or movie I&#8217;ve watched. This leads me to search the internet for this very specific scene and I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-63","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/posts\/63","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=63"}],"version-history":[{"count":4,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/posts\/63\/revisions"}],"predecessor-version":[{"id":82,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=\/wp\/v2\/posts\/63\/revisions\/82"}],"wp:attachment":[{"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=63"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=63"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kylehayhurst.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}