Tag Archives: ffmpeg

Fix makemkv not compiling in Arch

I’ve had my Arch Linux desktop system for several years now. Over that time, cruft has built up. It bit me today when I tried to install makemkv. No matter what I tried I could not get it to compile. Configure constantly failed an this step:

checking whether LIBAVCODEC_VERSION_MAJOR is declared... yes
checking LIBAVCODEC_VERSION_MAJOR... 52
...
configure: error: The libavcodec library is too old. Please get a recent one from http://www.ffmpeg.org

I had to systematically delete anything containing ffmpeg, then re-install ffmpeg, in order to finally get it to work.

Get a list of installed packages containing ffmpeg:

yay -Ss ffmpeg | grep Installed

Remove ffmpeg-containing packages:

yay -R chromaprint-fftw grilo-plugins gst-plugins-bad cheese gnome-music gnome-video-effects totem ffmpeg-compat-54 ffmpeg-compat-57 ffmpeg0.10 ffmpeg4.4 vlc libavutil-52 faudio

Install makemkv:

yay -S makemkv

My “nuke all ffmpeg from orbit” approach worked. After I did so, makemkv compiled!

Convert music to iPhone ringtones

I’ve recently crossed into the dark side and gotten my first iPhone. I wanted to set up ringtones for my contacts but discovered that Apple is pretty picky about ringtone file format. After some searching I found the ffmpeg command to run to get the ringtones into a file iPhones are happy with.

The criteria are:

  • aac codec
  • m4r filename
  • 30 seconds or less in duration

I ran into a snag with various things I was trying to convert apparently having more than one stream. I would get the error message

Could not find tag for codec h264 in stream #0, codec not currently supported in container

I had to use the map command to specify exactly which stream I wanted (just the audio one.) I discovered which stream I wanted by running the ffmpeg -i command on the file to see its available streams. I also discovered that some songs reported incorrect duration. This was fixed with the -write_xing 0 option. Thanks to this gist for the inspiration.

Here is the full command to turn music into an Apple-compatible ringtone. Modify -ss and -to to suit your needs (starting time, to ending time)

ffmpeg -i <input file> -codec:a aac -ss 00:00:59.5 -to 00:01:21.5 -f ipod -map 0:0 -write_xing 0 ringtone.m4r

If taking a ringtone from a video file, I had to specify I wanted stream 1 instead of stream 0:
ffmpeg -i Batman-\ The\ Animated\ Series\ -\ S02E01\ -\ Shadow\ of\ the\ Bat\ \(1\)\ SDTV.avi
-codec:a aac -ss 00:00:20.5 -to 00:00:43.5 -f ipod -write_xing 0 -map 0:1 batman_ringtone.m4r

Once you have the right m4r file, you simply need to plug your iPhone into your computer and fire up iTunes. You can then drag the file into the "Tones" section on the left under "Devices".


Merge multiple MP4 files into one with ffmpeg concat

I had a bunch of MP4 files I wanted to merge into a single file. FFMpeg came to the rescue, but it had a bit of a quirk I needed to figure out. Thanks to this site for the help.

First, create a list of files you wish to merge. In this example I want every file with a specific file pattern beginning with 2019-05-02. I take that output and run sed against it to add “file ‘” to the begging and a closing ” ‘ ” at the end. The end result is a nice list of files for ffmpeg to ingest.

ls 2019-05-02* | sed "s/^/file '/g; s/$/'/g" > filelist.txt

With our shiny new list we can now tell ffmpeg to use it to concatenate to a single file:

ffmpeg -f concat -safe 0 -i filelist.txt -c copy OUTPUT_FILENAME.mp4

Rotate videos for WordPress using ffmpeg

WordPress has an extremely annoying issue with reading EXIF data when posting photos and videos. There is a plugin to fix rotated pictures, but I couldn’t find one for rotated videos. If you happen to upload a video from your phone that was shot in portait orientation, it will likely upload to wordpress in landscape orientation (sideways.) Very annoying.

My fix to this is to re-encode the video so it is at the proper orientation before uploading to wordpress. Thanks to this site for the information – ffmpeg does this automatically for you. So the syntax is simple:

ffmpeg -i SOURCE_VIDEO_FILENAME -c:a copy FIXED_VIDEO_FILENAME.mp4

Success.

Compile ffmpeg on CentOS 7

Recently I had to compile ffmpeg from scratch on CentOS 7. The reason? I wanted libfdk_aac support. Here are my notes on the procedure. The how-to on https://trac.ffmpeg.org/wiki/CompilationGuide/Centos was actually quite helpful and accurate.

Install necessary dependencies and set up build folder

yum install autoconf automake cmake freetype-devel gcc gcc-c++ git libtool make mercurial nasm pkgconfig zlib-devel
mkdir ~/ffmpeg_sources

Build necessary components
I only needed x264 and libfdk_aac, so that’s all I ended up doing:

#yasm
cd ~/ffmpeg_sources
git clone --depth 1 git://github.com/yasm/yasm.git
cd yasm
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin"
make
make install
make distclean
#libx264
cd ~/ffmpeg_sources
git clone --depth 1 git://git.videolan.org/x264
cd x264
PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static
make
make install
make distclean
#libfdk_aac
cd ~/ffmpeg_sources
git clone --depth 1 git://git.code.sf.net/p/opencore-amr/fdk-aac
cd fdk-aac
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
make
make install
make distclean

Compile ffmpeg
I actually specified a git mirror because the sources at ffmpeg site were glacially slow.

cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg.git
cd FFmpeg
PKG_CONFIG_PATH="$HOME/FFmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/FFmpeg_build" --extra-cflags="-I$HOME/FFmpeg_build/include" --extra-ldflags="-L$HOME/FFmpeg_build/lib" --bindir="$HOME/bin" --pkg-config-flags="--static" --enable-gpl --enable-nonfree --enable-libfdk-aac  --enable-libx264
make
make install
make distclean
hash -r

Optionally, remove existing ffmpeg

sudo yum remove ffmpeg

That was it! After a bit of compile time ffmpeg worked with the items I wanted it to.

Use FFMPEG to batch convert video files

Below are the tips and tricks I’ve learned in my quest to get all my family home movies working properly in Plex. I ended up having to re-encode most of them to have a proper codec.

ffmpeg is what I ended up using. Thanks to here and here I found a quality setting that I liked: x264 video with crf of 18 and veryslow encoder preset, AAC audio at 192kbps, mp4 container.

ffmpeg -i <file> -acodec libfdk_aac -b:a 192k -ac 2 -vcodec libx264 -crf 18 -preset veryslow <filename>.mp4

I tried to use exiftools to add metadata to the file but Plex wouldn’t read it. Instead I discovered you can use ffmpeg to encode things like title and date taken directly into the file. The syntax for ffmpeg is

-metadata "key=value"

The metadata values I ended up using were:

  • date – Plex looks at this
  • Title – what’s displayed in plex
  • comment – not seen by plex but handy to know about anyway

Encoding

My first pass at encoding combined find with ffmpeg to re-encode all my avi files. I used this command:

find . -name *.avi -exec ffmpeg -i {} -acodec libfdk_aac -b:a 192k -ac 2 -vcodec libx264 -crf 18 -preset veryslow {}.mp4 \;

Interrupted

I bit off more than I could chew with the above command. I had to kill the process because it was chewing up too much CPU. There are two ways to figure out which file ffmpeg is on:

ps aux|grep ffmpeg

will list the file that ffmpeg is currently working on. Take note of this because you’ll want to remove it so ffmpeg will re-encode it.

You can also run this command to see the last 10 most recently modified files, taken from here:

find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

Resume

Use the above command to remove what ffmpeg was working on when killed. Append -n to tell ffmpeg to exit and not overwrite existing files

find . -name *.avi -exec ffmpeg -n -i {} -acodec libfdk_aac -b:a 192k -ac 2 -vcodec libx264 -crf 18 -preset veryslow {}.mp4 \;

Cleanup

The command above gave me a bunch of .avi.mp4 files. To clean them up to just be .mp4 files combine find with some bash-fu (thanks to this site for the info)

find . -name “*.avi.mp4” -exec sh -c ‘mv “$1” “${1%.avi.mp4}.mp4″‘ _ {} \;

Finally, remove original .avi files:

find . -name "*.avi" -exec rm {} \;

 

Update 2/3/2016: Added a verification step.

Verification

Well, it looks like the conversion I did was not without problems. I only detected them when I tried to change the audio codec I used. You can use ffmpeg to analyze your file to see if there are any errors with it. I learned this thanks to this thread.

The command is:

ffmpeg -v error -i <file to check> -f null -

This will have ffmpeg go through each frame and log and tell you any errors it finds. You can have it dump them to a logfile instead by redirecting the output like so:

ffmpeg -v error -i <file to scan> -f null - >error.log 2>&1

What if you want to check the integrity of multiple files? Use find:

find . -type f -exec sh -c 'ffmpeg -v error -i "{}" -f null - > "{}".log 2>&1' \;

The above command searches for any file in the current directory and subdirectories, uses ffmpeg to analyze the file, and will output what it finds to a log file of the same name as the file that was analyzed. If nothing was found, a 0 byte file was created. You can use find to remove all 0 byte files so all that’s left are logs of files with errors:

find . -type f -size 0 -exec rm {} \;

You can open each .log file to see what was wrong, or do what I did and see that the presence of the log file at all means that the file needs to be re-encoded from source.

Checking the integrity of the generated files themselves made me realize I had to re-encode part of my home movie library. After re-encoding, there were no more errors. Peace of mind. Hooray!