Posts Tagged ‘ffmpeg’

Compile ffmpeg 64 bit on Windows with MSYS/MinGW-w64

Wednesday, January 8th, 2014

Set up the MSYS environment

Download MSYS from MinGW-builds. Extract it to a path with no spaces, to which you have write permissions. For example, D:\msys. This already includes useful features like pkg-config, Autotools and Git.

Download a pre-built MinGW-w64 from drangon.org and extract it inside the MSYS directory. This already includes useful features like Yasm.

Start MSYS with msys.bat

In MSYS, run:

echo 'export PATH=.:/local/bin:/bin:/mingw64/bin' > .profile
source .profile

Check that it has worked with gcc -v

Compile ffmpeg and libraries

These steps are similar to the Linux/BSD version of this guide.

git config --global core.autocrlf false
 
git clone git://git.videolan.org/x264.git x264
cd x264
./configure --host=x86_64-w64-mingw32 --enable-static --enable-shared && make && make install
cd ..
 
git clone git://github.com/mstorsjo/fdk-aac.git fdk-aac
cd fdk-aac
./autogen.sh
./configure --host=x86_64-w64-mingw32 --enable-static --enable-shared && make && make install
cd ..
 
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
./configure --enable-gpl --enable-nonfree --enable-libx264 --enable-libfdk_aac --enable-static --disable-shared --extra-cflags=-I/local/include --extra-ldflags='-L/local/lib -static' && make && make install

NOTE: configure on ffmpeg in mingw is slow. Be patient. You should also check for success after each library has compiled.

This should build ffmpeg.exe as a 64 bit static executable that can be run directly in Windows x64, with H.264 and AAC support. It does not need to be run from MSYS. In my testing, the 64 bit version is approx. 10% faster than the 32 bit version.

If you want it to use DLLs instead of creating a static executable, change --disable-shared to --enable-shared and remove the -static from the ldflags in the ffmpeg configure.

How to compile ffmpeg from source

Wednesday, June 9th, 2010

Windows users see here.


ffmpeg is a free and very powerful video encoding tool that is the basis of many other popular video encoding tools, with a command line interface.

Because of the frequent updates to ffmpeg and the codecs it uses, it is often best to download the latest source and compile it yourself. These updates usually include new features, bug fixes, support for new codecs and noticeable speed improvements. Most Linux distributions have outdated packages in their repositories so being able to compile the latest code from source is very useful

I use ffmpeg to output H.264 video with AAC audio in a MP4 container. I also occasionally convert audio to mp3. This means I will be compiling the following:

Preparing to compile on Linux

(If you already compile things on Linux, skip to the next section.)
First make sure that you have all of the tools and headers required to compile on Linux. On Debian based systems (including Ubuntu) you can usually run the following as root to get everything you need. First update your system. It is important that you get the latest kernel and the correct sources for it.

apt-get update
apt-get dist-upgrade

A reboot may be required here if your kernel updated.

Now get the compilers, tools and headers needed to compile software on Linux:

apt-get install build-essential linux-headers-`uname -r` git yasm

on FreeBSD:

pkg_add -r gmake git yasm

Compile ffmpeg (empty)

Because some libraries require ffmpeg to be installed, we will first install a blank copy with no additional codecs specified.

When I update, I often find that I need to recompile a blank version of ffmpeg before I can compile x264.

Download the latest ffmpeg source with git, configure, compile:

git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
./configure
make

If this all worked with no errors (you can check with echo $?), run

make install

as root. Use su or sudo if you need to. I use su.

Compile faac

Download and extract faac from audiocoding.com.

As above, run

./configure
make
su -c 'make install'

on both libraries.

You can optionally do the same thing with LAME if you want to be able to encode mp3 audio.

NB: if you get a strcasestr error compiling faac, just comment it out in faac_1.28/common/mp4v2/mpeg4ip.h

Compile x264

Download and compile the latest x264 source with git:

git clone git://git.videolan.org/x264.git x264
cd x264
./configure --enable-static --enable-shared
make
su -c 'make install'

Compile ffmpeg with the above codecs

Now that we have all of the codecs (x264, aac, mp3) successfully installed as libraries on the system, we can reinstall ffmpeg to incorporate these libraries. First go back to the ffmpeg source directory and clean off the previous compile.

cd ffmpeg
make clean

Now configure to enable all of the installed libraries and recompile:

./configure --enable-gpl --enable-nonfree --enable-pthreads --enable-libx264 --enable-libfaac --enable-libmp3lame --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib
make

If it all worked, run make install as root.

su -c 'make install'

Testing

As long as /usr/local/bin/ is on your $PATH environment variable, you should be able to just type ffmpeg to check that it is all installed. It should look something like this:

$ ffmpeg
FFmpeg version SVN-r23548, Copyright (c) 2000-2010 the FFmpeg developers
  built on Jun  9 2010 13:35:17 with gcc 4.4.4
  configuration: --enable-gpl --enable-nonfree --enable-pthreads --enable-libx264 --enable-libfaac --enable-libfaad --enable-libmp3lame
  libavutil     50.18. 0 / 50.18. 0
  libavcodec    52.75. 1 / 52.75. 1
  libavformat   52.68. 0 / 52.68. 0
  libavdevice   52. 2. 0 / 52. 2. 0
  libavfilter    1.20. 0 /  1.20. 0
  libswscale     0.11. 0 /  0.11. 0
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
 
Use -h to get full help or, even better, run 'man ffmpeg'

Using ffmpeg

I have written a small Python video encoding script to make encoding as easy as

enc -t cd file.vob

If anyone has any suggestions to improve this, please feel free to post them in the comments.

Convert any audio/video files to mp3 for free

Tuesday, November 24th, 2009

It seems that there is some confusion about audio conversion tools and some people even pay for them.

The truth is that most encoders, even ones you pay for, use ffmpeg internally to do all of the actual work and ffmpeg is free and open source.

You can even get it pre-compiled for Windows, though the version isn’t great.

The only problem with using ffmpeg directly is that it has a command line interface and most novices find it hard to use.

Here’s a batch file for use on Windows which will convert anything you drop onto the file into a 320kbps mp3:

ffmpeg -i %1 -ab 320k -y %1.mp3
@if errorlevel 1 @pause

To create this file, open notepad. Copy and paste the above 2 lines in. Save it as “convert.bat” or something similar (the .bat is important) and select “All files” from the drop down list.

Put the bat file in the same directory as ffmpeg.exe and simply drag anything you want converted on top of the bat file.

You can use almost anything. wav, m4a, m4v, mov, mpg, avi, etc. If you use a file with both audio and video, such as a movie, it will just extract the audio and save that as an mp3 file.

ffmpeg target file sizes (again)

Friday, July 17th, 2009

This script is now available as an ongoing project that can be downloaded. Please see the Video Encoding Project.


As a bit of a revision to a previous entry, I have converted the combination bash/python scripts I gave earlier into a single large python script.

This can now be used without editing any files to set sizes. An example of use is:
$ ./enc.py -s 700 -a 192 -o '-deinterlace' da_*.VOB
All of these flags are optional except the file list, where at least 1 file must be specified.

enc.tar.gz:

#!/usr/bin/python
 
from getopt import getopt, GetoptError
from sys import argv, exit
from subprocess import Popen, PIPE
from re import search
 
def secs(h, m, s):
  return (((h*60)+m)*60)+s
 
def calc_video_bitrate(target_bytes, ab, time):
  audio_bytes = (ab * 1000 / 8) * time
  return (target_bytes - audio_bytes) / time * 8
 
def get_duration(file):
  ffmpeg = Popen(("ffmpeg", "-i", file), stderr=PIPE)
  match = search("(\\d+):(\\d+):(\\d+)\\.\\d+", ffmpeg.communicate()[1])
  ffmpeg.stderr.close()
 
  if match == None: return 0
  dur = match.groups()
  return secs(int(dur[0]), int(dur[1]), int(dur[2]))
 
def encode(source, dest, opts, vbr, abr=128):
  command1 = "ffmpeg -i %s -pass 1 -an -vcodec libx264 -vpre fastfirstpass -b %d -bt %d -threads 0 %s -y pass1.mp4" % (source, vbr, vbr, opts)
  command2 = "ffmpeg -i %s -pass 2 -acodec libfaac -ac 2 -ab %dk -vcodec libx264 -vpre hq -b %d -bt %d -threads 0 %s -y %s" % (source, abr, vbr, vbr, opts, dest)
 
  pass1 = Popen(command1.split())
  pass1.wait()
 
  pass2 = Popen(command2.split())
  pass2.wait()
 
 
target_size = 350 #MiB
ab = 128 #kbps
extra_options = ""
 
# Parse args
try:
  opts, args = getopt(argv[1:], "s:a:o:", ["size=", "ab=", "opts="])
except GetoptError, err:
  print str(err)
  exit(2)
 
for o, a in opts:
  if o in ("-s", "--size"):
    target_size = int(a) * 1024 * 1024
  elif o in ("-a", "--ab"):
    ab = int(a)
  elif o in ("-o", "--opts"):
    extra_options = a
 
if len(args) < 1:
  print "Usage: " + argv[0] + \
    " [-s <size (MiB)>] [-a <audio bit rate (kbps)>] [-o <additional options>] <file list>"
  exit(2)
 
# Loop through files
for file in args:
  duration = get_duration(file)
  if duration <= 0:
    print "Unable to get length of", file
    continue
 
  bitrate = calc_video_bitrate(target_size, ab, duration)
 
  encode(file, file + ".mp4", extra_options, bitrate, ab)

How to set target file sizes in ffmpeg

Tuesday, June 16th, 2009

This script is now available as an ongoing project that can be downloaded. Please see the Video Encoding Project. This post describes the methods and mathematics behind the script.


After much searching, I found almost nothing regarding how to target a specific file size with ffmpeg, such as 700MiB to fit on a CD. Almost everything I found suggested to use a negative bitrate for mencoder, such as -700000. However, this did not work for me at all (even by copying and pasting verbatim). Because of this, I set about doing it manually with some mathematics.

What I am going to do here assumes a single audio stream, a single video stream and nothing else in the output file at all (i.e. no subtitles, no alternate languages, no director’s commentaries, etc).

When encoding media, audio uses a constant bit rate. This means that you can calculate how much space it will take if you know which bit rate you are using and how long the stream is in seconds. This also means that to know how big the video stream should be, we can calculate how big the audio stream will be and subtract it from the target file size. For example, if the target file size is 350MiB and the audio will take up 30MiB, we know the video should aim to be 320MiB (ignoring overheads in the multiplexing, container headers, etc). We can use the same calculations in reverse to work out an average or constant bit rate from a file size and a length in seconds.

In this example, I will be using Dad’s Army Series 6 Episode 1 – The Deadly Attachment. I have already ripped this from the DVD with SlySoft AnyDVD and PgcDemux on Windows. Automating PgcDemux rips is worth a whole entry in itself. Note that I have bought this legally and I do not intend to sell or share it. I just want a copy that I can store on my network and play from any computer. Storing 14 DVD images on hard drives takes quite a lot of space, which is where encoding comes in handy. In fact, some of my box sets contain over 60 DVDs (roughly 270GiB).

———-
To install ffmpeg on Debian, it is best to get it from the Debian Multimedia repository. Add

deb http://www.debian-multimedia.org lenny main
deb-src http://www.debian-multimedia.org lenny main

to your /etc/apt/sources.list and then run

# apt-get update
# apt-get install debian-multimedia-keyring
# apt-get update
# apt-get install ffmpeg

———-

The first thing we need to do to put this into practice is to get the length of the stream. If you supply the file to ffmpeg without telling it to do anything, it will give you an error. However, this error already contains all of the information we need:

$ ffmpeg -i da_6_01.VOB
FFmpeg version SVN-r13582, Copyright (c) 2000-2008 Fabrice Bellard, et al.
  configuration: --prefix=/usr ...
  built on May  3 2009 12:07:18, gcc: 4.3.2
Input #0, mpeg, from 'da_6_01.VOB':
  Duration: 00:29:23.90, start: 0.287267, bitrate: 5987 kb/s
    Stream #0.0[0x1e0]: Video: mpeg2video, yuv420p, 720x576 [PAR 16:15 DAR 4:3], 9800 kb/s, 25.00 tb(r)
    Stream #0.1[0x80]: Audio: ac3, 48000 Hz, stereo, 192 kb/s
Must supply at least one output file

We can see that the duration is 00:29:23.90.

As this is an error, we need to redirect stderr to stdout. This can be done with 2>&1. We then need the line that contains the “Duration”, which we can get with grep. We can cut this line up to take the time out.

$ ffmpeg -i da_6_01.VOB 2>&1 | grep Duration | cut -d ' ' -f 4 | cut -d '.' -f 1
00:29:23

This can be converted into seconds with the formula s' = (h * 60 + m) * 60 + s.

I used a python script to do this and to perform the necessary calculations mentioned earlier. Note that most of this python script is just for the convenience of getopts and that, if needed, it can be cut down significantly at the cost of flexibility. If you always want the same output size and audio bitrate, this script can be simplified to just a couple of lines.

calc_bitrate.py:

#!/usr/bin/python
 
from getopt import getopt, GetoptError
from sys import argv, exit
 
def secs(h, m, s):
  return (h * 60 + m) * 60 + s
 
def calc_video_bitrate(target_size, abr, time):
  target_bytes = target_size * 1024 * 1024
  audio_bytes = ((abr * 1000) / 8) * time
  return (target_bytes - audio_bytes) / time * 8
 
try:
  opts, args = getopt(argv[1:], "s:a:t:", ["size=", "abr=", "time="])
except GetoptError, err:
  print str(err)
  exit(2)
 
target_size = 350 #MiB
abr = 128 #kbps
time = 0
 
for o, a in opts:
  if o in ("-s", "--size"):
    target_size = int(a)
  elif o in ("-a", "--abr"):
    abr = int(a)
 
if len(args) < 1:
  print "Usage: " + argv[0] + " [-s <size (M)>] [-a <audio bit rate (k)>] [[hh:]mm:]ss"
  exit(2)
 
time_part = args[0].split(":")
if len(time_part) < 2: time_part = [0] + time_part
if len(time_part) < 3: time_part = [0] + time_part
time = secs(int(time_part[0]), int(time_part[1]), int(time_part[2]))
 
print "%d" % calc_video_bitrate(target_size, abr, time)

A typical usage for this would be ./calc_python.py -s 350 -a 128 29:23.

We can then use a combination of these inside a shell script easily. I’m using bash syntax just to nest the commands into a single line but for compatibility with other shells, backticks (`) can be used and this is what I normally prefer. This script loops through all of the .VOB files in the directory and gives their target video bitrate for a 350MiB output and 128kbps audio.

#!/bin/bash
 
for vob in *.VOB
do
  BR=$(./calc_bitrate.py -s 350 -a 128 $(ffmpeg -i $vob 2>&1 | grep Duration | cut -d ' ' -f 4 | cut -d '.' -f 1))
  echo $vob $BR
done

I use this in 2-pass VBR mode with the libx264 video encoder and libfaac audio encoder in an mp4 container just by replacing the “echo” line of the above script with the following 2 lines:

ffmpeg -i $vob -an -pass 1 -vcodec libx264 -vpre fastfirstpass -b $BR -bt $BR -deinterlace -threads 0 -y pass1.mp4
ffmpeg -i $vob -acodec libfaac -ab 128k -ac 2 -pass 2 -vcodec libx264 -vpre hq -b $BR -bt $BR -deinterlace -threads 0 -y `echo $vob | sed 's/VOB/mp4/'`

I have 2 versions of this script, one with “-deinterlace” and one without. PAL video (576i – used in Europe), such as Dad’s Army needs deinterlacing. NTSC video (480 – used in North America) usually does not.

For ripping DVDs to H.264 and maintaining the quality, I wouldn’t use a bitrate lower than 1000k or an audio bitrate lower than 128k stereo. This means that for getting media onto a CD, you probably want no smaller than 350MiB for 30 to 40 minutes or 700MiB for 1 hour or more, depending on your resolution. Also note that I only intend to play these in computers and fitting them onto CDs is just a convenience – standalone DVD players will not be able to play H.264 or AAC (Blu-ray and HDDVD players may be able to – mp4 containers and reading CDs would be more of an issue).

Update:

I have successfully tested this in a LG BD370 Blu-ray player.

I have not tried actually burning these onto CDs yet so if 2 won’t fit on a 700MiB CD, even with overburn (because of overheads that were ignored, as stated earlier) then the simplest solution is to just target a smaller file size with something like “-s 348″.

The result

Dad’s Army episodes are not all of the same length. Some are several minutes longer than others. The following shows how no matter the size of the input file, they all produce the same size output file:

$ ll da_5_*.VOB
-r--r--r-- 1 mythtv mythtv 1364660224 2009-06-04 00:01 da_5_01.VOB
-r--r--r-- 1 mythtv mythtv 1360699392 2009-06-04 00:01 da_5_02.VOB
-r--r--r-- 1 mythtv mythtv  956084224 2009-06-04 00:02 da_5_03.VOB
-r--r--r-- 1 mythtv mythtv 1355888640 2009-06-04 00:02 da_5_04.VOB
-r--r--r-- 1 mythtv mythtv 1114351616 2009-06-03 23:59 da_5_05.VOB
-r--r--r-- 1 mythtv mythtv 1034289152 2009-06-04 00:00 da_5_06.VOB
-r--r--r-- 1 mythtv mythtv 1045202944 2009-06-04 00:00 da_5_07.VOB
-r--r--r-- 1 mythtv mythtv 1345318912 2009-06-04 00:00 da_5_08.VOB
-r--r--r-- 1 mythtv mythtv 1391529984 2009-06-04 00:02 da_5_09.VOB
-r--r--r-- 1 mythtv mythtv 1342748672 2009-06-04 00:03 da_5_10.VOB
-r--r--r-- 1 mythtv mythtv 1158017024 2009-06-04 00:03 da_5_11.VOB
-r--r--r-- 1 mythtv mythtv 1157097472 2009-06-04 00:03 da_5_12.VOB
-r--r--r-- 1 mythtv mythtv 1180098560 2009-06-04 00:04 da_5_13.VOB
$ ll -h da_5_*.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 06:18 da_5_01.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 06:55 da_5_02.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 07:30 da_5_03.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 08:08 da_5_04.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 08:44 da_5_05.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 09:21 da_5_06.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 09:58 da_5_07.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 10:36 da_5_08.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 11:15 da_5_09.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 11:54 da_5_10.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 12:29 da_5_11.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 13:05 da_5_12.mp4
-rw-r--r-- 1 mythtv mythtv 352M 2009-06-17 13:41 da_5_13.mp4

Update:

A pure python replacement script is available here that simplifies use.