FFmpeg Batch .mov > .gif conversion - ffmpeg

I am trying to batch convert a folder of .mov's into .gif's.
Input .mov's are 1920x1080 resolution and I would like to convert to 720x480 (to save file size). I have the following code, but not sure how to add the -vf scale=720 into this code:
for i in *.mov; do ffmpeg -ss 1 -i "$i" "${i%.*}.gif"; done
The above code works, just running it through terminal. Any help on adding the scale or any other optimizations to reduce file size would be greatly appreciated.
Thanks

for i in *.mov; do ffmpeg -ss 1 -i "$i" -vf "fps=10,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 "${i%.*}.gif"; done
Combination of:
How do I convert a video to GIF using ffmpeg, with reasonable quality?
How do you convert an entire directory with ffmpeg?

Related

Batch extracting frames from multiple mp4 file

So i have a folder with only mp4 files. I just want to get specific frames for every mp4 files automatically. I tried the below command, but it tried overwriting the mp4 file, is there any error with the below command? So i expect to input a mp4 file and to get 3 frames in .jpg format.
for i in *.mp4; do
ffmpeg -i *.mp4 -vf select='eq(n\,10)+eq(n\,17)+eq(n\,21)' -vsync 0 frames%d.jpg
done
I am no expert on ffmpeg but you have some fairly fundamental issues in your script. Hopefully, this will get you started:
for i in *.mp4; do
ffmpeg -i "$i" -vf select='eq(n\,10)+eq(n\,17)+eq(n\,21)' -vsync 0 "${i%.*}_frames%d.jpg"
done

Add multiple audio files to video at specific points using FFMPEG

I am trying to create a video out of a sequence of images and various audio files using FFmpeg. While it is no problem to create a video containing the sequence of images with the following command:
ffmpeg -f image2 -i image%d.jpg video.mpg
I haven't found a way yet to add audio files at specific points to the generated video.
Is it possible to do something like:
ffmpeg -f image2 -i image%d.jpg -i audio1.mp3 AT 10s -i audio2.mp3 AT 15s video.mpg
Any help is much appreciated!
EDIT:
The solution in my case was to use sox as suggested by blahdiblah in the answer below. You first have to create an empty audio file as a starting point like that:
sox -n -r 44100 -c 2 silence.wav trim 0.0 20.0
This generates a 20 sec empty WAV file. After that you can mix the empty file with other audio files.
sox -m silence.wav "|sox sound1.mp3 -p pad 0" "|sox sound2.mp3 -p pad 2" out.wav
The final audio file has a duration of 20 seconds and plays sound1.mp3 right at the beginning and sound2.mp3 after 2 seconds.
To combine the sequence of images with the audio file we can use FFmpeg.
ffmpeg -i video_%05d.png -i out.wav -r 25 out.mp4
See this question on adding a single audio input with some offset. The -itsoffset bug mentioned there is still open, but see users' comments for some cases in which it does work.
If it works in your case, that would be ideal:
ffmpeg -i in%d.jpg -itsoffset 10 -i audio1.mp3 -itsoffset 15 -i audio2.mp3 out.mpg
If not, you should be able to combine all the audio files with sox, overlaying or inserting silence to produce the correct offsets and then use that as input to FFmpeg. Not as convenient, but guaranteed to work.
One approach I can think of is to create your audio file for the whole duration of the video first and then mux the audio with the video file

How to extract the 1st frame and restore as an image with ffmpeg?

Anyone knows the trick?
And how to install ffmpeg ? yum install mpeg only returns this:
======================================================================================== Matched: mpeg ========================================================================================
libiec61883.i386 : Streaming library for IEEE1394
libiec61883.x86_64 : Streaming library for IEEE1394
qffmpeg-devel.i386 : Development package for qffmpeg
qffmpeg-devel.x86_64 : Development package for qffmpeg
qffmpeg-libs.i386 : Libraries for qffmpeg
qffmpeg-libs.x86_64 : Libraries for qffmpeg
I've cobbled up this command line from various answers that works great for me to get the absolutely first frame out from a video. I use this to save a thumbnail screenshot for the video.
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -q:v 3 output_image.jpg
Explanation:
The select filter -vf "select=eq(n\,0)" is to select only frame #0.
-q:v allows you to set the quality of the output jpeg between 1 and 31. Lower the number, higher the quality. 2 - 5 works good, I use 3.
Note: This will get you an image with the same size as the video. To get a thumbnail, you can use the scale filter to get a thumbnail to fit whatever width you need, like so:
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -vf scale=320:-2 -q:v 3 output_image.jpg
The above command will give you a thumbnail jpeg that will be scaled to match width of 320, and height will be calculated to match the aspect ratio.
It's on the manpage:
* You can extract images from a video, or create a video from many
images:
For extracting images from a video:
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
This will extract one video frame per second from the video and will
output them in files named foo-001.jpeg, foo-002.jpeg, etc. Images
will be rescaled to fit the new WxH values.
If you want to extract just a limited number of frames, you can use
the above command in combination with the -vframes or -t option, or in
combination with -ss to start extracting from a certain point in time.
But of course you have to install it first. I'm on Debian and don't use yum.
[update for the other question]
i=1
for avi in *.avi; do
ffmpeg -i $avi -vframes 1 -f image2 /tmp/$i.jpg; i=$((i+1))
done
Tested and works.
[update for yet another question...]
for flv in *.flv; do
ffmpeg -i $flv -vframes 1 -f image2 ${flv%%.flv}.jpg
done
An easy to grok solution that works for me is
ffmpeg -i <input> -vframes 1 <output>.jpeg
Note that I do get an error "[swscaler # 0x111652000] deprecated pixel format used, make sure you did set range correctly" but according to a little reading (see for example https://stackoverflow.com/a/43038480/1241736) that can safely be ignored.
It's works for me
ffmpeg -i sample-mp4-file.mp4 -ss 1 -vframes 1 output.jpg

ffmpeg -is it possible to increase a clip duration?

I currently have a jpeg file which I converted to an flv using the following command:
ffmpeg -r 10 -b 180000 -i test.jpg test.mp4
Now, I want to increase the duration of this .mp4 clip, so the picture stays on the screen for more than a split second. Eventually, I hope to merge a stream of these files to create a slide show out of jpeg files.
Does anyone know how to increase the duration of a clip in ffmpeg?
Looping the input and setting a duration should achieve the effect you want:
ffmpeg -loop_input -i test.jpg -t 10 test.mp4
Doing something like this should work (at least for a single image):
ffmpeg -loop_input -i picture.jpg -r 1 -vcodec flv -b 192k -i Music.mp3 -acodec copy -shortest output.flv
I bet you could get it working with multiple images by adding more inputs though I haven't tested.
(http://forum.videohelp.com/threads/280695-FFMPEG-Loop-input-video)

Create animated gif from a set of jpeg images

I need something that can be scripted on windows 7. This image will be used in banners.
Simon P Stevens' answer almost got me there:
ffmpeg -f image2 -i image%d.jpg video.avi
ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif
Let's see if we can neaten this up.
Going via an avi is unnecessary. A -pix_fmt of rgb24 is invalid, and the -loop_output option prevents looping, which I don't want. We get:
ffmpeg -f image2 -i image%d.jpg out.gif
My input pictures are labeled with a zero-padded 3-digit number and I have 30 of them (image_001.jpg, image_002.jpg, ...), so I need to fix the format specifier
ffmpeg -f image2 -i image_%003d.jpg out.gif
My input pictures are from my phone camera, they are way too big! I need to scale them down.
ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299 out.gif
I also need to rotate them 90 degrees clockwise
ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif
This gif will play with zero delay between frames, which is probably not what we want. Specify the framerate of the input images
ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif
The image is just a tad too big, so I'll crop out 100 pixels of sky. The transpose makes this tricky, I use the post-rotated x and y values:
ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1,crop=299,431,0,100 out.gif
The final result - I get to share my mate's awesome facial expression with the world:
You can do this with ffmpeg
First convert the images to a video:
ffmpeg -f image2 -i image%d.jpg video.avi
(This will convert the images from the current directory (named image1.jpg, image2.jpg...) to a video file named video.avi.)
Then convert the avi to a gif:
ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif
You can get windows binaries for ffmpeg here.
You can also do a similar thing with mplayer. See Encoding from multiple input image files.
I think the command line would be something like:
mplayer mf://*.jpg -mf w=800:h=600:type=jpg -vf scale=160:120 -vo gif89a:fps=3:output=out.gif
(Where 800 & 600 are your source width and height and 160 & 120 are the target width and height.out.gif is your target file name)
I've just tested both of these and they both work fine. However I got much better results from mplayer as I was able to specify the resolution and framerate. Your milage may vary and I'm sure you could find more options for ffmpeg if you looked.
With ImageMagick:
convert *.png a.gif
The ffmpeg to .avi and .avi to .gif worked, but the only thing to note is that your images must be named in perfect increasing numeric order to work, with no gaps. I cooked up a quick python script to rename all of my images accordingly so that this ffmpeg recipe would work:
import os
files = [ f for f in os.listdir('.') if os.path.isfile(os.path.join('.',f)) and f.endswith('.jpg') ]
for i, file in enumerate(sorted(files)):
os.rename(file, 'image%03d.jpg' % i)
And then I stumbled upon a much simpler approach than ffmpeg for doing the conversion, which is simply using ImageMagick's command line convert tool like this
convert image%03d.jpg[0-198] animated_gif.gif
Doesn't get much simpler than that folks.
Gist here: https://gist.github.com/3289840
Based on the answers of Simon P Stevens and dwurf I came up with this simplified solution:
ffmpeg -f image2 -framerate 1 -i image%d.jpg video.gif
This results in a rate of 1 second per image. Adjust the framerate value according to your needs.
I'd just like to add to dwurf's answer, that this will generate a gif with the standard 256-colors palette, which does not look very visually pleasing.
I've found two blog-posts and adapted them to my needs, in order to improve the visual quality by using a custom palette for your animation:
Generate the color palette:
ffmpeg -f image2 -i image%d.jpg -vf scale=900:-1:sws_dither=ed,palettegen palette.png
Convert images into a regular video with the desired framerate, because the third command only worked with a single input video and not a bunch of images
ffmpeg -f image2 -framerate 1.2 -i image%d.jpg video.flv
Now convert the generated video with the generated palette into a more beautiful gif:
ffmpeg -i video.flv -i palette.png -filter_complex "fps=1.2,scale=900:-1:flags=lanczos[x];[x][1:v]paletteuse" video.gif

Resources