Get FFMPEG with all the options which is a little more complicated in brew because the Homebrew team removed all options from the core formula:
brew update
brew uninstall --force --ignore-dependencies ffmpeg
brew install chromaprint amiaopensource/amiaos/decklinksdk
brew tap homebrew-ffmpeg/ffmpeg
brew upgrade homebrew-ffmpeg/ffmpeg/ffmpeg $(brew options homebrew-ffmpeg/ffmpeg/ffmpeg | grep -vE '\s' | grep -- '--with-' | grep -vi chromaprint | tr '\n' ' ')
sudo apt update
sudo apt install ffmpeg
To validate that it's installed properly: ffmpeg -version
ffmpeg -i file.mov -c copy out.mp4
you can remove audio by using the -an
flag
MJPEG
(motion-jpeg): an example here and if you are making videos from JPEG images, try-c:v copy
as recommended herex264
: the unofficial cheatsheet on stackoverflowx265
(aka High Efficiency Video Coding): full tutorial here on OTTVerse
ffmpeg -i input.mov -vcodec libx264 -crf 20 output.mp4
The CRF, which, in this case, is 20, can range from 18 to 24, where a higher number will compress the output to a smaller size.
The video codec used here is x264, to check what encoding input.mov
is do:
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nokey=1:noprint_wrappers=1 input.mov
Reference from here
or more commonly referred to as trimming
use the -ss
option to specify a start timestamp, and the -t
option to specify the encoding duration. The timestamps need to be in HH:MM:SS.xxx format or in seconds
Example for clipping 10 seconds, 30 seconds from the start:
ffmpeg -ss 00:00:30.0 -i input.wmv -c copy -t 00:00:10.0 output.wmv
ffmpeg -ss 30 -i input.wmv -c copy -t 10 output.wmv
Note that -t is an output option and always needs to be specified after -i
.
Use the -to
arg to specify the target end time
Also note that if you specify -ss
before -i
, -to
will have the same effect as -t
, i.e. it will act as a duration.
ffmpeg -i input.mp4 -vf scale=$w:$h output.mp4
where $w
is width and $h
is height (e.g. -vf scale=640:480
will resize the video to 480p
To get the width, height of a video, you could(ref):
ffprobe -v error -select_streams v -show_entries stream=width,height -of csv=p=0:s=x input.mp4
for small resolutions, check here or here.
ffmpeg -i <input> -filter:v fps=fps=30 <output>
using PTS filter, to slow down video to half the speed:
ffmpeg -i input.mkv -filter:v "setpts=2.0*PTS" output.mkv
to double the speed (frames might be dropped, however, which can be avoided by increasing the FPS: see here):
ffmpeg -i input.mkv -filter:v "setpts=0.5*PTS" output.mkv
To take every 15th frame, use
ffmpeg -i in.mp4 -vf select='not(mod(n,15))',setpts=N/FRAME_RATE/TB out.mp4
Another method is to use the framestep filter
ffmpeg -i in.mp4 -vf framestep=15,setpts=N/FRAME_RATE/TB out.mp4
see this useful post or even this one that combines with a gifsicle
compression:
ffmpeg -i input.mp4 -s 1400x800 -pix_fmt rgb24 -r 30 -f gif output.gif
gifsicle output.gif --optimize=3 --delay=3 --colors 64 -o output.gif
- the
-s
params is optional but it's for the output video width, height - the
-r
params controls the FPS --optimize
is the compression level in gifsicle, 3 being the highest--colors
set how many color is in the gif (less being more compressed, see the GIF Compression section below)
But to do the Boomerang effect, you might want something like this where input.mp4
is the segment that you want to loop and rewind (source):
ffmpeg -i input.mp4 -filter_complex "[0]reverse[r];[0][r]concat=n=2:v=1:a=0" output.gif
it's best handled by gifsicle
(brew install gifsicle
), see this solution for reference.
ffmpeg -i filename
For more see this post
ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames input.mp4
see here for details
but to be faster, you probably wanna count packets instead which is significantly faster from experience:
ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4
The font file path you need is probably gonna be at /usr/share/fonts
on Linux or '/Library/Fonts/'
on MacOS
ffmpeg -i input.mp4 -vf "drawtext=fontfile=Arial.ttf: text='Frame\: %{frame_num}': start_number=0: x=(w-tw)/2: y=h-(2*lh): fontcolor=black: fontsize=20: box=1: boxcolor=white: boxborderw=5" -c:a copy output.mp4
This create a video that's like this:
ffmpeg -i input.mp4 -q:a 0 -map a output_file.m4a
-q:a
: variable bitrate with 0 being the highest quality-map a
: select audio stream only- file extension, in general
m4a
is a good idea because ffmpeg should be smart enough to guess your intent and figure out the right codec of your output audio file and encapsulate the raw AAC into the output M4A container
ffmpeg -i /input/track1.m4a -i ~/input/track2.m4a -filter_complex '[0:0][1:0]concat=n=2:v=0:a=1[out]' -map '[out]' output/track.m4a
for adding a third track simple replace [0:0][1:0]concat=n=2
with [0:0][1:0][2:0]concat=n=3
ffmpeg -ss 01:23:45 -i input -frames:v 1 -q:v 2 output.jpg
- the
-ss
flag indicates the timestamp of the frame in hh:mm:ss - for details see this stackoverflow post
using 30 fps (for details see this stackoverflow post):
ffmpeg -framerate 30 -pattern_type glob -i '*.jpg' -c:v libx264 -pix_fmt yuv420p out.mp4
the command expects that in your working directories there are a list of JPEGs nicely named by frame number and ideally zero padded. In case you want to make them zero padded, this stackoverflow answer might help.
if you bump into the height not divisible by 2
error you might want to add a pad filter: -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"
as explained here.
Finally, if you want to do this with the ffmpeg-python
package, this example might help.
See this very detailed guide or borrow from this solution:
ffmpeg \
-i input1.mp4 \
-i input2.mp4 \
-filter_complex vstack=inputs=2 \
output.mp4
this explains video keyframes in the context of compression in details. To see how keyframes are extracted, this post is helpful. And to see how many keyframes are in your video, check this
For cropping video in the same way one would on images, see this post
rotation are set in the metadata of the video
to add rotation data, use ffmpeg:
ffmpeg -i input.mp4 -metadata:s:v rotate=180 -vcodec copy -acodec copy output.mp4
this should be lossless because of -vcodec copy
, for more details see this stackoverflow post
to update rotation data, use exiftools (not tested, install with sudo apt install libimage-exiftool-perl
):
exiftool -rotation=180 input.mp4
see reference here