Terminology

Cropping and cutting have the same meaning but movie processing software seems to distinguish between the two:

  • cropping a movie means to slice the visual canvas.
  • cutting a movie means to slice out a sequence of it.

Crop a Movie

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.

Trimming a Movie

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.

Convert FLAC to MP3 Recursively

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.

Lowering the Quality of Movies

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.

Convert Movies to iPad Format

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

Scale Movies

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.

Speed-up Movies

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.

Split Clips into Equal Segments of a Given Size

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.

Preparing Video for Web Serving

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.

Converting FRAPs Videos

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.

Trim Metadata

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.

Strip Audio from Video Clip

ffmpeg -i input.mp4 -c copy -an output.mp4

Install a Full FFmpeg Distribution on Debian

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

Convert Video to GIF Animation

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 second

Now, 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 $4$ times the current speed,
  • -r 1 will drop or duplicate frames to achieve $7$ 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 size

In 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 $1$ duplicate frame out of $4$,
  • fps=8 - attempt to set the framerate to $8$ frames per second,
  • setpts=0.35*PTS - speed up the movie by $0.35$ of the original speed.

Lowest Common Denominator Settings Compatible with All Sites

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 \
  -tune zerolatency
  output.mp4

Capture WebCam to Framebuffer

The following command will capture video from /dev/video0, at 320x240 resolution and send it to the Linux framebuffer:

ffmpeg -f v4l2 -video_size 320x240 -i /dev/video0 -pix_fmt bgra -f fbdev /dev/fb0

The command can be used, for example, to display a webcam to screen directly without needing to install the X window system.

Adding Subtitles to Videos

  • as optional subtitles:
ffmpeg -i "movie.mp4" -i "movie.srt" -c copy -c:s mov_text output.mp4

where:

  • movie.mp4 is the movie,
  • movie.srt are the subtitles in SRT format,
  • output.mp4 is the output movie
  • as burnt into the video (requires ffmpeg compiled with –enable-libass):
ffmpeg -i movie.mp4 -vf subtitles=movie.srt output.mp4

or with libass:

ffmpeg -i movie.srt movie.ass
ffmpeg -i movie.mp4 -vf ass=movie.ass output.mp4

where:

  • movie.mp4 is the movie,
  • movie.srt are the subtitles in SRT format,
  • output.mp4 is the output movie

Concatenating or Merging Multiple Files

Given several files such as:

  • a.mkv
  • b.mkv
  • c.mkv

the files can be concatenated together into one large merged movie by following the steps:

  • create a list of files with a format specific to the ffmpeg concatenate filter, assuming that files are named sequentially:
for i in $(find . -name \*.mkv); do echo "file '$(realpath $i)'"; done >> list.txt
  • merge the files together with ffmpeg:
ffmpeg -loglevel info -f concat -safe 0 -i list.txt -c copy "Merged Movie.mkv"

Normalizing the Size of Video Clips

Sometimes it is necessary to normalize the size of multiple video clips. For example, the clips extracted for learning morse code ended up having different sizes that made the video player change size every single letter was displayed.

The following command:

for i in *.mp4; do ffmpeg -i "$i" -vf "crop=w='420':h='420',scale=420:420,setsar=1" conv/"$i"; done

will batch-change the size of all MP4 files in the same directory and store them inside a conv sub-directory.

This method is called crop-and-scale meaning that the video clip is cropped to a fixed size and then scaled to a fixed size. The only drawback in doing this is that whilst the size of the video clips will be the same for all the clips, the content might be distorted depending on the original video clip.

Determining if A Video File has Fast Start Enabled

Issue:

ffmpeg -v trace -i FILE 2>&1 | grep -e type:'\mdat\' -e type:\'moov\'

where:

  • FILE is a video file

This will yield output similar to the following:

mov,mp4,m4a,3gp,3g2,mj2 @ 0x5578f2e712c0] type:'moov' parent:'root' sz: 2586269 40 344228747
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5578f2e712c0] type:'mdat' parent:'root' sz: 341642438 2586317 344228747

If moov appears before mdat then the faststart flag is set on the video file.


fuss/ffmpeg.txt · Last modified: 2024/01/14 23:08 by office

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.