This is an old revision of the document!
Cropping and cutting have the same meaning but movie processing software seems to distinguish between the two:
The following command:
ffmpeg -i example.mov -filter:v "crop=w:h:x:y" result.mov
trims a movie called example.mov
and outputs the result in result.mov
. The trimming is performed by selecting a rectangle, w
pixels wide by h
pixel high, starting from the screen coordinates x
and y
from the top-left corner of the screen.
The following example:
ffmpeg -i example.mov -ss 00:00:02 -t 00:00:28 result.mov
cuts a slice starting from 2s
into the movie and cuts out 28s
starting from that point.
The following command goes through the directories starting from where the command was issued and converts FLAC files to MP3 files. The one-liner requires ffmpeg
and lame
to be installed.
Input file:
./TIPWCD001 - Various Artists - Halluci-Nations (1999)/06_Process_-_Blue_Moonies.flac
Output file:
./TIPWCD001 - Various Artists - Halluci-Nations (1999)/06_Process_-_Blue_Moonies.mp3
find . -name "*.flac" -exec sh -c 'ffmpeg -y -i "{}" -acodec libmp3lame -ab 320k "${0/flac/mp3}"' {} \;
Note that this preserves the FLAC files and does not delete them.
The following command:
ffmpeg -i example.mov -r 24 -b:v 256k result.mp4
takes as input example.mov
and lowers the framerate to 24fps
and sets the video bitrate to 256k
.
It appears that scaling the movie down to a smaller resolution increases the filesize instead of lowering it.
The IFS
changes is required in order to process file names with spaces.
OLDIFS=$IFS IFS=$(echo -en "\n\b") for i in *.avi; do ffmpeg -i $i -acodec aac -ac 2 -vcodec libx264 -strict experimental -threads 24 -profile:v baseline -preset ultrafast -level 30 -ab 160k -b 1200k -f mp4 ${i/avi/mp4} done IFS=$OLDIFS
Using -vf
for ffmpeg >= 0.9
:
ffmpeg -i input.mp4 -vf scale=iw/4:-1 output.mp4
where iw
stands for input width
which is then divided by 4
. The -1
indicates that ffmpeg
should preserve the ration and scale the height accordingly.
Sometimes, this will not work because the width and height is not divisible by 2
. To avoid that, you can issue:
ffmpeg -i input.mp4 -vf "scale=720:trunc(ow/a/2)*2" output.mp4
which will scale the width to 720
and adjust the height according to that value.
Using the setps
video filter:
ffmpeg -i input.mp4 -vf setpts=0.5*PTS output.mp4
will double the speed of the movie in the output file.
The following code is an adaptation from Antarctic Nest of Icephoenix and will split clips into equal segments of a given size.
To use, save the file as ffmpeg-split.py
and then run:
chmod +x ffmpeg-split.py
in order to make it executable.
Then, clips can be split using the command:
./ffmpeg-split.py -f someclip.wav -s N
where N
represents the number of seconds that each segment will have.
########################################################################### ## Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 ## ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## ## rights of fair usage, the disclaimer and warranty conditions. ## ########################################################################### # Original version can be found at Antarctic Nest of Icephoenix at: # # http://icephoenix.us/notes-for-myself/auto-splitting-video-file-in- # # -equal-chunks-with-ffmpeg-and-python/ # ########################################################################### #!/usr/bin/env python import subprocess import re import math from optparse import OptionParser length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,' re_length = re.compile(length_regexp) def main(): (filename, split_length) = parse_options() if split_length <= 0: print "Split length can't be 0" raise SystemExit output = subprocess.Popen("ffmpeg -i '"+filename+"' 2>&1 | grep 'Duration'", shell = True, stdout = subprocess.PIPE ).stdout.read() print output matches = re_length.search(output) if matches: clip_length = int(matches.group(1)) * 3600 + \ int(matches.group(2)) * 60 + \ int(matches.group(3)) print "Clip length in seconds: "+str(clip_length) else: print "Can't determine clip length." raise SystemExit split_count = int(math.ceil(clip_length/float(split_length))) if(split_count == 1): print "Clip length is less then the target split length." raise SystemExit # -acodec copy and -vcodec copy will not give accurate results so do not use them split_cmd = "ffmpeg -i '"+filename+"' " for n in range(0, split_count): split_str = "" if n == 0: split_start = 0 else: split_start = split_length * n split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \ " '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \ "'" print "About to run: "+split_cmd+split_str output = subprocess.Popen(split_cmd+split_str, shell = True, stdout = subprocess.PIPE).stdout.read() def parse_options(): parser = OptionParser() parser.add_option("-f", "--file", dest = "filename", help = "file to split, for example sample.avi", type = "string", action = "store" ) parser.add_option("-s", "--split-size", dest = "split_size", help = "split or chunk size in seconds, for example 10", type = "int", action = "store" ) (options, args) = parser.parse_args() if options.filename and options.split_size: return (options.filename, options.split_size) else: parser.print_help() raise SystemExit if __name__ == '__main__': try: main() except Exception, e: print "Exception occured running main():" print str(e)
One of the important changes from the original is that the -acodec
and -vcodec
parameters are not used which guarantees an accurate split down to the frames. By omitting these parameters, ffmpeg
is allowed to re-encode which guarantees that clip lengths are accurate. This is due to the fact that all the frames between key-frames in a clip are a function of those key-frames and if we were to cut between those key-frames then there would not be any information available to decode the clip.
The most compatible video format up to date is MP4:
ffmpeg -i input.mp4 -profile:v 'baseline' -pix_fmt yuv420p \ -r 25 -crf 18 -vcodec libx264 -vb 448k \ -acodec libfdk_aac -ar 44100 -ac 2 -b:a 96k \ -movflags faststart -strict experimental output.mp4
the command uses faststart
that moves the moov
metadata to the beginning of the file so the file can be played while being downloaded.
FRAPs captures videos in AVI format and if you want to use them on OSX, they will have to be converted first using ffmpeg
(which can be installed using homebrew). To convert the video, issue:
ffmpeg -i input.avi -acodec libfdk_aac -b:a 128k -vcodec mpeg4 -b:v 1200k -flags +aic+mv4 output.mp4
libfdk_aac
is the best encoder at the time of writing but it may not be recognised depending on how your ffmpeg
was compiled - if that happens, try libfaac
or aac
.
Trimming metadata contained in a media-file can be accomplished with ffmpeg
by providing the extra switch -map_metadata -1
. This particularly works well with MP3 files that have embedded metadata when creating them under OS X.
ffmpeg -i input.mp4 -c copy -an output.mp4
deb-multimedia packages a full ffpmeg
with all plugins. Add the following lines to /etc/apt/sources.list
:
deb http://www.deb-multimedia.org stable main non-free deb-src http://www.deb-multimedia.org stable main non-free
and then issue:
apt-get update
to update the package list; followed by:
apt-get install deb-multimedia-keyring
to install the keyring for the repo and then update with aptitude
:
aptitude update
Finally, uninstall any existing ffmpeg
:
aptitude purge ffmpeg
and install the new ffmpeg
with:
aptitude install ffmpeg x264
A typical usage case of FFMpeg is to convert a video file into a GIF animation. Assuming an input video named anim.mp4
, the conversion can be performed rather simply by issuing:
ffmpeg -i anim.mp4 anim.gif
where:
anim.mp4
is the input video,anim.gif
is the resulting GIF.Unfortunately, the generate GIF file will be very large and might appear very slow. This is mostly due to ffmpeg trying to maintain the framerate such that it will generate as many frames as necessary.
The first step is to dump all frames of the video file to a GIF file:
ffmpeg -i anim.mp4 -r 1 dump.gif
where:
-r 1
will lower the framerate to 1 frame per secondNow, the resulting file should be very large, so to reduce the size, the obtained file will be converted to another GIF file by lowering the framerate and specifying the amount of frames to skip:
ffmpeg -i dump.gif -vf "setpts=0.25*PTS" -r 7 final.gif
setpts=0.25*PTS
will set the speed as times the current speed,-r 1
will drop or duplicate frames to achieve frames per second
Achieving an acceptable GIF is a games of push and pull between the value of -r
and the value of setpts
.
Other very useful filters are:
decimate
- will merge / drop duplicate frames hence lowering the GIF size,deflicker
- will attempt to stabilize the video,scale
- will scale the movie (down) and hence can be used to lower the file sizeIn one pass:
ffmpeg -i a.gif -vf "deflicker, decimate=cycle=4, fps=8, setpts=0.35*PTS, scale=360:trunc(ow/a/2)*2" b.gif
the actions performed will be:
deflicker
- attempt to deflicker / stabilize the video,decimate=cycle=4
- crop duplicate frames at a rate of duplicate frame out of ,fps=8
- attempt to set the framerate to frames per second,setpts=0.35*PTS
- speed up the movie by of the original speed.
The settings produce an output file with the faststart
flag such that the video can be sought through without having to buffer the entire file.
ffmpeg -i $INPUT_FILE \ -c:v libx264 -crf 23 -profile:v baseline -level 3.0 -pix_fmt yuv420p \ -c:a aac -ac 2 -b:a 128k \ -movflags faststart \ output.mp4