Thursday 18 April 2013

Time Lapse Videos of the Garden (2 of 3)

The camera looking out to the garden has been running for a while now. Since about the 28th of March given the date of my last post on it. As you can imagine it has gathered quite a large collection of images, 18,000 at the last count! So I thought it would be a good a time as any to give another time lapse video a try.

I used the same script as last time but made a slight change so it would create a copy of each image with a 5 digit number rather than 4 (cause we have over 9999 images) and out the video with a greater frame rate (20fps instead of 4).

x=0; for i in *jpg; do counter=$(printf %05d $x); cp "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done
ffmpeg -f image2 -r 20 -y -i /tmp/img%05d.jpg garden.avi
rm /tmp/img*

The results were less than satisfactory (don't watch the whole video, the first minute or so gets the point across):
Garden Time Lapse Test 3

As you can see the video is riddled with artifacts making viewing pretty unenjoyable and ruining the time lapse effect.

A quick check on a few images shows they are being captured fine so the problem must be in the video making process.

A bit of googling turns up some possible reasons:
  • If you don't give the type of codec you want to use then an old one is used by default.
  • If you don't give the bitrate you want to use then one is made up (estimated really but given the quality it might as well be made up).
[This section still didn't fix the problem, skip ahead to "Ok, this time I am following the official ffmpeg with x264 compilation page from start to finish. Here goes..." for the actually solution]

Advice on additional arguments that can be passed to improve things are also given. Here is the source of the advice on StackOverflow and here is the revised script with the additional arguments:

x=0; for i in *jpg; do counter=$(printf %05d $x); cp "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done
ffmpeg -f image2 -b 5M -minrate 1M -r 20 -y -i /tmp/img%05d.jpg garden.avi
rm /tmp/img*

Sadly it made little difference and my video still came out looking like crap.

The advice also states that the best codec to use is the libx264 one. Since my server didn't have that installed I had to go install it as follows:

cd src
wget http://ftp.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
tar -xjvf /path/to/x264-snapshot-20080805-2245.tar.bz2
cd x264-snapshot-20130409-2245/
./configure --enable-shared --disable-asm
make
sudo make install
sudo ldconfig

(Thanks to this blog for the information.)

Then revise the code:

x=0; for i in *jpg; do counter=$(printf %05d $x); cp "$i" /tmp/img"$counter".jpg; x=$(($x+1)); done
ffmpeg -f image2 -b 5M -minrate 1M -r 20 -vcodec libx264 -y -i /tmp/img%05d.jpg garden.avi
rm /tmp/img*

And here are the results:

Unknown decoder 'libx264'

Pants, looks like I need to rebuild ffmpeg as well. So it is back to this blog for the information which is pretty much the next steps. Annoyingly it means I have to install SVN. Here's the summary:

sudo apt-get purge ffmpeg
cd src
sudo apt-get install subversion
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
cd ffmpeg
./configure --enable-libx264 --enable-gpl --enable-shared --disable-yasm
make
sudo make install
sudo ldconfig

I also created the file /etc/ld.so.conf.d/custom-libs.conf and added the line /usr/local/lib then called sudo ldconfig as per his fix for something else so that the x264 library could be found. It still wasn't. The result was still the same:

Unknown decoder 'libx264'

What a pain this is! One last try then I'm coming back to it tomorrow. I've rebooted, let's see if that's fixed it...no.

[Some time passes, maybe a day, maybe a little longer...]

Right I'm back.

Even after the reboot libx264 still can't be found by ffmpeg despite being in the /usr/local/lib directory and having the dir added to /etc/ld.so.conf.d/custom-libs.conf so let's see what's up.

locate libx264.so should find it but returns nothing.

A look at the official ffmpeg with x264 compilation page shows that it follows a slightly different step after calling make in both the x264 and ffmpeg compilation. Instead of calling sudo make install it calls sudo checkinstall with a few arguments. Let's see if jumping back into the x264 directory and calling checkinstall is enough:

sudo checkinstall --pkgname=x264 --pkgversion="20130409-2245" --backup=no --deldoc=yes --fstrans=no --default

Unknown decoder 'libx264'

Nope. What if I make ffmpeg again with checkinstall:
sudo checkinstall --pkgname=ffmpeg --pkgversion="26402" --backup=no --deldoc=yes --fstrans=no --default

Unknown decoder 'libx264'

Nope. DAMN IT!

So it looks like I either need to clean out all the make stuff before I call checkinstall or, even better, just wipe out the whole lot and start again. I think that is what I'm going to do...

[Some more time passes...]

Ok, this time I am following the official ffmpeg with x264 compilation page from start to finish. Here goes...

The following steps were followed to the letter, check the page for their gory details:
  1. Remove everything.
  2. Re-install everything plus a bit more.
  3. Create a symbolic link to FFMPEG in /usr/local/bin.
  4. Remove the bitrate options from the video making script cause FFMPEG now complains about them.
  5. Scream because it still comes up "Unknown decoder 'libx264'" only now it's in a different colour!
So some more researching and a random Stack Overflow article suggests calling 'ffmpeg -codecs' to see if there is a 'libx264' line. Calling this turns up a huge amount of results so I suggest calling:

ffmpeg -codec | grep 264

instead. Doing so turns up one result:

DEV.LS h264        H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb )

Notice the name is h264 rather than libx264. Just out of curiosity I gave this line a try:

ffmpeg -f image2 -r 20 -y -i /tmp/img%05d.jpg -codec h264 garden.avi

And so far it seems to be working (it's slow and there is now 20,000+ images as the camera has been running since I started).

Notice I've moved the -codec argument to just before the output file, I think this lets ffmpeg know I want to use it for encoding and not decoding. I've changed the codec called to h264 instead of -libx264. Maybe this is using a different codec, maybe it is calling the libx264 one by the right name. At this point I'm tired, fed up and losing the will to live. I just want the video to come out looking decent!

Here is the output from FFMPEG (10 minutes in):

Input #0, image2, from '/tmp/img%05d.jpg':
  Duration: 00:19:43.35, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj422p, 640x480, 20 fps, 20 tbr, 20 tbn, 20 tbc
No pixel format specified, yuvj420p for H.264 encoding chosen.
Use -pix_fmt yuv420p for compatibility with outdated media players.
[libx264 @ 0xb067ec0] using cpu capabilities: MMX2 SSE2 Cache64
[libx264 @ 0xb067ec0] profile High, level 3.0
Output #0, avi, to 'garden.avi':
  Metadata:
    ISFT            : Lavf55.2.100
    Stream #0:0: Video: h264 (H264 / 0x34363248), yuvj420p, 640x480, q=-1--1, 20 tbn, 20 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (mjpeg -> libx264)
Press [q] to stop, [?] for help
frame=12500 fps=8.5 q=28.0 size=   68222kB time=00:10:22.85 bitrate= 897.3kbits/s

and here is the resulting video:
Garden Time Lapse Test 4


Finally! Great quality! Way too long but great quality throughout!

So maybe I could have called that command from the start, maybe not, I'll never know. I'm just glad to finally have it finally working.

Next up I think I'll play with the times images are taken and the rate of playback or the rate of capture. I'm also playing with the idea of a bigger project where I try and install the camera outside but we'll just have to wait and see.

Until then, happy computing and happy gardening!

No comments:

Post a Comment