Skip to content

Instantly share code, notes, and snippets.

@nonoesp
Created March 19, 2020 15:57
Show Gist options
  • Save nonoesp/d54f7b905c2c6a9d3c14db27c721ff34 to your computer and use it in GitHub Desktop.
Save nonoesp/d54f7b905c2c6a9d3c14db27c721ff34 to your computer and use it in GitHub Desktop.

Work-in-progress document. These notes are loosely arranged and named. Take what you may. Thanks to @garciadelcast for contributing with his discoveries!


Here is a guide with personal notes to use FFmpeg and Imagemagick to automate all kinds of tricks in gif creation, video conversion, frame extraction, image processing, and more. These notes express a love for automating the automatable.

ffmpeg and convert (from ImageMagick)

FPS=1x30
FRAMES=10

# Export frames from video
fs:
	@ffmpeg \
	-i loop.mov \
	-vf fps=$(FRAMES) \
	frames/f_%02d.jpg

# Convert frames to GIF
gif:
	@convert \
	-delay $(FPS) \
	-geometry 1400x800 \
	frames/*.jpg \
	bin/@15fps-$(FPS).gif

Extract Frames from Video, Create GIF, Create Boomerang GIF

You need to have this Makefile inside a folder that contains an input.mp4 video. Then run:

make init
make gif

And here is the code for this commands.

gif:
	ffmpeg -i input.mp4 -vf fps=10 frames/f_%02d.jpg
	convert -delay 1x30 -geometry 800x400 frames/* -loop 0 bin/default.gif
	convert -coalesce bin/default.gif -delete -1 -delete 0 -reverse -coalesce bin/default.gif -loop 0 bin/boomerang.gif

init:
	mkdir frames
	mkdir bin

Trimming (time selection)

Use -ss 00:00:04 for start time (this would be second four to start)

Use -t 00:00:02 for duration (this would be two seconds after second four)

This would basically extract frames from second 4 to second 6.

Cropping

2600x1800 is the new canvas size we want the image to have, and 0x0 is the offset of the corner of the canvas.

convert \
-delay 1x1 \
frames/*.jpg \
-crop 2600x1800+0+0 +repage \
bin/ts-debug.gif

Reference

Inbox

Add all images with the jpg extension

ffmpeg -framerate 1 -pattern_type glob -i '*.jpg' video.mp4

Imagemagick

Rotate images without changing canvas

convert image.jpg -distort SRT -45 output_image.png

Extract frames

extract_original:
	ffmpeg -i $(video_in) -vf fps=$(FPS) $(path)/$(name)_%02d_out.jpg

extract_resized:
	ffmpeg -i $(video_in) -vf scale=-1:$(resize_width),fps=$(FPS) $(path)/$(name)_%02d_out.jpg	

Create gif from frames

gif:
	convert -delay 1x$(frames) $(path)/* bin/gif-$(resize_width)p-1x$(frames)-FPS$(FPS).gif

Create video from frames

video:
	ffmpeg -y -framerate $(frames) -pattern_type glob -i '$(path)/*.jpg' out.mp4	

Notes from Jose Luis García del Castillo y López (@garciadelcast)

TIMELAPSE

MILLING The pieces rotates over the roughing in around 20180622_142000

TESTS Couldn’t really figure out a way to just input all images in the folder to ffmpeg. Instead, did a massive renaming with Windows PowerShell:

$ Dir | %{Rename-Item $_ -NewName ("sanding_{0:d5}.jpg" -f $nr++)}

Then, used ffmpeg to stitch them into a timelapse:

$ ffmpeg -framerate 30 -i sanding_%05d.jpg sanding_timelapse.mp4

MAC Do all files on a folder? This works on Mac

ffmpeg -framerate 30 -pattern_type glob -i '*.jpg' video.mp4

To rename files, followed this answer: https://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers#

a=1
for i in *.jpg; do
  new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
  mv -i -- "$i" "$new"
  let a=a+1
done

Worked great!

The milling video has a lot of corrupt jpegs, can skip them with this?

https://stackoverflow.com/a/45986689

ffmpeg -err_detect aggressive -fflags discardcorrupt -i rtsp://[ip address]:554/11 -r 1 -s 640x320 -an -f image2 c:\temp\snapshots\snapshot-%03d.jpg

This is actually going the other way around...

Tried this:

ffmpeg -framerate 30 -fflags discardcorrupt -pattern_type glob -i '*.jpg' video.mp4

Didn’t work. Cleaned them with this: https://stackoverflow.com/questions/4780424/detecting-corrupted-images-in-bash-script

for f in *.jpg ; do identify $f > /dev/null || echo $f >> /tmp/fail ; done ; cat /tmp/fail

FINAL MILLING So, ended up doing this to create a file with the list of bad files, and remove them:

for f in *.jpg ; do identify $f > /dev/null || (identify $f 2>> removed.txt ; rm $f) ; done ;

This means

for loop AND do identify and send non stderr to null output (no output) OR (if the previous operation yielded error) then do both identify and pipe stderr with append to removed.txt AND remove file

(that looks awful lol) It cleaned almost 2k JPEGs.

Then created the video with

ffmpeg -framerate 30 -fflags discardcorrupt -pattern_type glob -i '*.jpg' video.mp4

This worked great and didn’t crash after 10 mins of video. I guess the crashing was happening because of the 2k corrupted JPEGs. It still gave me a bunch of EOI missing, emulating errors, but gave me none after the large corrupted batch, and went all way through with the 60k frames.

→ F**k, I need to crop the larger images! Also, there are still images with EOI missing creating flickering… Solve this!

To solve the remaining EOI files, used this:

for f in *.jpg ; do identify -verbose -regard-warnings $f > /dev/null || (identify -verbose $f 2>> removed_EOI.txt ; rm $f) ; done ; 

-verbose deep searches the file, yielding the right errors (although makes the thing slow AF) -regard-warnings makes identify return false on warning, hence triggering the removal Source: https://www.imagemagick.org/discourse-server/viewtopic.php?t=20045

There are larger images at 2304x1536 that need to be resized & cropped to 1080p:

mogrify -resize 1920x1080^ -gravity center -extent 1920x1080 *.jpg

mogrify is like convert, but overwrites images the ^ operator fits the smaller dimension to the image. -extent is like -crop but only keeps the focus part, doesn’t give you the crops too

GIF but in video with FFMPEG

Create a video with, for instance, 1x4 (4 frames per second).

ffmpeg -framerate 4 -fflags discardcorrupt -pattern_type glob -i '*.jpg' video.mp4

Create a list.txt file with the following contents to loop the video:

file 'video.mp4'
file 'video.mp4'
file 'video.mp4'
file 'video.mp4'

Then do

ffmpeg -f concat -i list.txt -c copy output.mp4

[Update 190213] Mogrify to batch convert jpgs

mogrify -format jpg -path output_folder input_folder/*.jpg

Extract mp3 from an mp4 videos

This will extract the audio of any mp4 videos in your current folder with the same name of the original video.

find . -type f -name "*.mp4" -exec bash -c 'FILE="$1"; ffmpeg -i "${FILE}" -vn -c:a libmp3lame -y "${FILE%.mkv}.mp3";' _ '{}' \;

Source

Extract mp3 from an mkv videos

This will extract the audio of any mkv videos in your current folder with the same name of the original video.

find . -type f -name "*.mkv" -exec bash -c 'FILE="$1"; ffmpeg -i "${FILE}" -vn -c:a libmp3lame -y "${FILE%.mkv}.mp3";' _ '{}' \;

Source


videogrep

(Script from Daniel Shiffman.)

Created with videogrep by Sam Lavigne. https://github.com/antiboredom/videogrep

1. Install youtube-dl (https://ytdl-org.github.io/youtube-dl...)
2. youtube-dl https://www.youtube.com/channel/UCvjg... -f 22 --write-auto-sub
3. videogrep -i *.mp4 --use-vtt --search "your search terms"

[Updated 2019.10.24] Square images to add padding (and resize)

Images are converted to the resize size first, then padded (or extended) to have the desired width and height, gravitating from the center and filling the background as white.

convert -background white -gravity center * -resize 1000x1000 -extent 1000x1000 result.png

2020.01

Some new commands from Jose Luis.

Speeding video up with ffmpeg

ffmpeg -i input.mp4 -an -filter:v "setpts=0.1*PTS" output.mp4
  • 0.1 accelerates x10 by dropping frames, 0.01 would accelerate x100 and so on.
  • -an removes audio.

Lossless cropping/trimming videos with ffmpeg

ffmpeg -i input.mp4 -ss 00:00:00 -to 01:30:15 -c:v copy -c:a copy output.mp4

Omit the -to parameter to trim till the end. Use -t parameter instead to specify duration, not end time.

Improved GIF making with palette per frame

Was doing a GIF/MP4 [and] exported all pages from PDF as PNGs in Acrobat, and then used imagemagick to compose them as two-page spreads:

magick montage *.png -geometry 637x825 -tile 2x1 -background black spread.png

Using typical GIF generation with palette and ffmpeg:

ffmpeg -y -i spread-%02d.png -vf palettegen palette.png
ffmpeg -r 6 -y -i spread-%02d.png -i palette.png -filter_complex "paletteuse" cad2raster.gif

Problem was, this was failing because the palette is generated from only one frame (the first), and since the cover was black and white, it was making the whole thing black and white. Same problem with MP4—even without using the palette.

Reading this article, I found a [one-liner] solution. It generates a GIF/MP4 creating one palette per frame:

ffmpeg -r 2 -i spread-%02d.png -filter_complex "[0:v] split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1" catalog.gif

I am not really sure what most of the parameters do, but it worked!

Downscale or Downsize

ffmpeg -i input.mp4 -vf scale=1920:1080 -c:v libx264 smaller.mp4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment