{"id":2458,"date":"2026-05-12T23:00:36","date_gmt":"2026-05-13T03:00:36","guid":{"rendered":"https:\/\/www.unliterate.net\/?p=2458"},"modified":"2026-05-12T23:00:37","modified_gmt":"2026-05-13T03:00:37","slug":"ffmpeg-shortcuts-in-2026","status":"publish","type":"post","link":"https:\/\/www.unliterate.net\/index.php\/2026\/05\/12\/ffmpeg-shortcuts-in-2026\/","title":{"rendered":"ffmpeg shortcuts in 2026"},"content":{"rendered":"\n<p>I have a couple of one-offs that I use when working with the videos that I&#8217;ve taken. I either need to do one thing or another, but I keep coming back to a couple basic actions.<\/p>\n\n\n\n<p>This is my dump of my <a href=\"https:\/\/www.ffmpeg.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">FFmpeg<\/a> shorts.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Animated Gifs<\/h2>\n\n\n\n<p>Usually I&#8217;m creating &#8220;many&#8221; animated gifs, and I wasn&#8217;t exactly sure of dimensions, size, or framerate so a loop was always relevant. This typically gets embedded in a bash script, where $1 is the parameter passed into the script. Adjust the HEIGHT or FPS variables as needed, but these values always gave me good results.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for HEIGHT in \"450\" \"300\" \"150\"; do\n  for FPS in \"15\" \"10\" \"5\"; do\n    ffmpeg -i \"$1\" -filter_complex \"&#91;0:v] fps=$FPS,scale=$HEIGHT:-1:flags=lanczos,split &#91;a]&#91;b];&#91;a] palettegen &#91;p];&#91;b]&#91;p] paletteuse\" \"$1\"_\"$HEIGHT\"_\"$FPS\".gif\n  done\ndone<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Infinite Loop<\/h2>\n\n\n\n<p>Good, short videos, especially for website backgrounds, can get looped easily and cleanly with the right set of commands. It&#8217;s really a 2-step process: (1) reverse the video, (2) concatenate the videos. $1 being the source filename.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># make reverse\nffmpeg -i \"$1\" -vf reverse rev_\"$1\"\n\n# ffmpeg\nffmpeg -i \"$1\" -i rev_\"$1\" \\\n -filter_complex \"&#91;0:v:0]&#91;1:v:0]concat=n=2:v=1&#91;outv]\" \\\n -map \"&#91;outv]\" vidlooper.mp4<\/code><\/pre>\n\n\n\n<p>There are two ways to do the concatenation, with the first using the &#8220;concat&#8221; filter and a list of files as the input. The second way is the recommended way to <a href=\"https:\/\/trac.ffmpeg.org\/wiki\/Concatenate#differentcodec\" data-type=\"link\" data-id=\"https:\/\/trac.ffmpeg.org\/wiki\/Concatenate#differentcodec\" target=\"_blank\" rel=\"noreferrer noopener\">concatenate files of separate codecs<\/a> which has better results than using the filter alone.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Streaming Video<\/h2>\n\n\n\n<p>This one got a bit complicated the more I learned of it. The final result is so I can use <a href=\"https:\/\/videojs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">video.js<\/a> to stream large videos, like a vimeo or youtube channel.<\/p>\n\n\n\n<p>The input is $1, and two additional parameters I&#8217;ve adapted: $VIDEOFOLDER is the name of the folder to place all files, and $FILENAME9 is the first 9 digits of the file hash of the video to make the end result filenames unique across a large swatch of videos I&#8217;ve had to encode.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffmpeg \\\n  -i \"$1\" \\\n  -filter_complex '&#91;0:v]split=1&#91;v1]; &#91;v1]copy&#91;v1out];' \\\n  -map &#91;v1out] \\\n  -c:v:0 libx264 \\\n  -x264-params nal-hrd=cbr:force-cfr=1 \\\n  -b:v:0 5M \\\n  -maxrate:v:0 5M \\\n  -minrate:v:0 5M \\\n  -bufsize:v:0 10M \\\n  -preset slow \\\n  -g 48 \\\n  -sc_threshold 0 \\\n  -keyint_min 48 \\\n  -map a:0 \\\n  -c:a:0 aac \\\n  -b:a:0 128k \\\n  -ac 2 \\\n  -f hls \\\n  -hls_time 15 \\\n  -hls_playlist_type vod \\\n  -hls_flags independent_segments \\\n  -hls_segment_type mpegts \\\n  -hls_segment_filename \"$VIDEOFOLDER\/$FILENAME9-data%04d.ts\" \\\n  -master_pl_name \"$FILENAME9-master.m3u8\" \\\n  -var_stream_map v:0,a:0 \\\n  \"$VIDEOFOLDER\"\/\"$FILENAME9\".m3u8<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Video Dimensions<\/h2>\n\n\n\n<p>Programmatically I can pull dimensions of a video with ffprobe, and even determine if the multimedia file is a video or not due to the lack of data returned. The only data returned is comma-separated.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 \"$1\"<\/code><\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have a couple of one-offs that I use when working with the videos that I&#8217;ve taken. I either need to do one thing or another, but I keep coming back to a couple basic actions. This is my dump of my FFmpeg shorts.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,20,17],"tags":[],"class_list":["post-2458","post","type-post","status-publish","format-standard","hentry","category-centos","category-geek-instructions","category-linux"],"_links":{"self":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/2458","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/comments?post=2458"}],"version-history":[{"count":1,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/2458\/revisions"}],"predecessor-version":[{"id":2459,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/2458\/revisions\/2459"}],"wp:attachment":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/media?parent=2458"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/categories?post=2458"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/tags?post=2458"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}