Sep 23, 2010

Getting XBMC to work with Beyond TV's chapters.xml files

XBMC doesn't appear to read Beyond TV's commercials skip files (named file.chapters.xml), although it has support for them.

I found that recent Beyond TV software writes these files out as Unicode (UTF-16) which probably confuses XBMC. So I wrote this quick Python script to convert all the chapter files given on the command line to UTF-8 in /tmp. Save it as "convert_chapters.py" and run with "python convert_chapters.py *.chapters.xml"
#!/usr/bin/python
# Convert all the files given on command line from utf-16 to utf-8 in /tmp

import os.path, sys, codecs

for filename in sys.argv[1:]:
    f = codecs.open(filename, encoding="utf-16")
    data = f.read()
    f.close()
    newfilename = "/tmp/%s" % os.path.basename(filename)
    f = codecs.open(newfilename, "w", encoding="utf-8")
    f.write(data)
    f.close()
The newly converted files work under XBMC now. They do not appear as chapters (chapter skip still does not use this information) but as sort of on-the-fly video editing information. When you reach the commercials while viewing a recorded video you'll see XBMC doing an automated skip to the end of the commercial block, so you don't even have to reach for the remote.

Note: on Windows there is no "/tmp" so you should replace that with an appropriate location. Or you can replace newfilename with filename in the codecs.open() call and have it overwrite the chapter files in place - but make sure to make a backup first in case things don't go as planned!

Sep 15, 2010

Creating time-lapse videos under Linux with EXIF stamps

Time-lapse videos accelerate an event tens or thousands of times faster than it really happened. They're usually created with a digital camera by shooting a sequence of photos taken at fixed intervals (say, every minute), hence, some time lapses between each "frame". To help this task, some digital cameras come with an intervalometer function where you set the start time, interval and number of pictures and leave the camera to do the rest.

Now we have a bunch of photos and need to make a movie out of it. In Linux, the easiest way is to use mencoder from the MPlayer package, or ffmpeg. Side note: to get the fully-capable mplayer package on Fedora you need to use the RPM Fusion repositories (both free and non-free).

The following command creates a high-quality 720p H264 AVI movie, suitable for uploading to YouTube, from all the jpg photos in the current folder and using a frame rate of 3 photos per second (fps=3).
mencoder "mf://frames/*.jpg" -mf fps=3 -ovc x264 -nosound \
          -x264encopts crf=16:me=umh:ssim:ref=1:b_adapt=2 \
          -vf scale=-11:720,hqdn3d,pp=al \
          -o video-720p.avi

Now I want to tag the video with the time, to get an idea of how fast it went, and add more data from the EXIF headers. We need two more tools to do this: convert and exiftool, for which you need to install the ImageMagick (or GraphicsMagick) and perl-Image-ExifTool packages.
Captioned time-lapse movie frame
A movie using the above format can be made with the following shell script. It is very customizable, you can add or remove text, change fonts and colors etc.  Here goes, save this in timelapse.sh:

#!/bin/bash
# Convert the pictures given on the command line into a time-lapse movie
# Author: Laurentiu Badea, Sep 15, 2010

FPS=3      # frame rate, in frames per second
VIDEO_HEIGHT = 720   # make a 720p movie. Other options: 1080, 480, 240...

start=$1
if [ ! -f "$start" ]; then echo "Usage $0 *.jpg"; exit 1; fi
[ -d "frames" ] || mkdir "frames" || exit 1

HEIGHT=`identify -format "%[height]" "$start"`
PTS=$[$HEIGHT*50/1000]   # calculate font size proportional to image size

for f in $*; do
  echo "$f"

  # format image timestamp. See "man strftime" for all format options.
  TEXT1=`exiftool -d "%l:%M%P" -p '$CreateDate' "$f"`

  # prepare EXIF data. See "exiftool -j yourimage.jpg" for more tags.
  TEXT2=`exiftool -p '$Model $FocalLength f/$Aperture ${ShutterSpeed}s ISO$EXIF:ISO' "$f"`

  convert "$f" \
    -gravity SouthWest \
    -font "Courier-Bold" \
    -fill "black" \
    -pointsize $PTS \
    -annotate +$PTS+$[3*$PTS/2] "$TEXT1" \
    -font "Times-Roman" \
    -fill "rgba(90%,90%,90%,0.4)" \
    -pointsize $[$PTS*2/3] \
    -annotate +$PTS+$[$PTS/2] "$TEXT2" \
    -gravity SouthEast \
    -annotate +$PTS+$[3*$PTS/2] "©2010" \
    -compress none \
    frames/${f/.*/.tif}
done

[ "$VIDEO_HEIGHT" -gt "$HEIGHT" ] && VIDEO_HEIGHT="$HEIGHT"
set -x
mencoder "mf://frames/*.tif" -mf fps=$FPS -ovc x264 -nosound \
         -x264encopts crf=16:me=umh:ssim:ref=1:b_adapt=2 \
         -vf scale=-11:$VIDEO_HEIGHT,hqdn3d,pp=al \
         -o video-${VIDEO_HEIGHT}p.avi
set +x
#rm -rf frames    # leave this commented out to try the mencoder line manually
I save the frames as TIF to avoid some quality loss if they were saved as jpeg again. That takes a lot of space so you may want to use jpg instead. Also they are saved at full resolution with convert, and I let mencoder to the scaling. This again wastes some space but avoids widths that make the video unplayable.

You'll notice sometimes the colors are specified as rgba(90%,90%,90%,0.4). That makes a transparent color. The first three numbers are R,G,B (0%-100%) and the last one is the opacity or alpha channel, from 0.0 (fully transparent) to 1.0 (completely opaque).

You can add more text, just remember that convert reads the commands sequentially, like a program (that is why I laid it out that way) and each -annotate command uses the most recent settings that appeared before it.

Don't make the text too obtrusive. It's hard to resist, but you don't want the viewers to be distracted or annoyed by stuff they don't care for. Transparency helps to let the text blend in more and disappear if you don't look specifically for it. Another option is add a black border below the image where to write. A better option is to leave the video stream untouched and put the data in a separate stream, for example, as subtitles. This may be the subject of a future post.

Mar 4, 2010

Luxeon LED lighting retrofit for Marineland Eclipse 3 aquarium hood

The Marineland Eclipse 3 aquarium hood comes from the factory with two 18W fluorescent tubes that need to be replaced once a year to maintain their light output. This article documents replacing the fluorescent lighting with over 1000 lumens of LED lighting for 13W of power and less maintenance.


LED advantages:
  • Low power (probably half that of fluorescent)
  • Cool light (in the sense of no emitted heat) and less dissipated heat into tank means better water temperature control in warm rooms.
  • Much longer life (Luxeons are quoted at 50,000hrs for 70% light output) and consistent light spectrum
  • Better illumination pattern, does not need mirrors, does not waste light. Less light on front wall means less algae. Can be collimated with add-on lenses for tall tanks.
  • No more high-voltage in the hood.
  • Dimming control.
  • Natural-looking underwater light shimmer due to waves interfering with a point light source. Fluorescents produce very uniform lighting because of their large surface.
  • Avoid having to deal with hazardous material disposal (fluorescent lights cannot be thrown into trash).
LED technology is improving very fast these days, I expect consumer versions of high-power LEDs will make their way in stores soon in standard forms and at cheaper prices, making this sort of upgrade easier, not that this was too hard.

Philips Lumileds' new generation of Luxeon Rebel LEDs can put out 180 lumens each, running at 3.4V, 700mA, which works out to about 78lumens/W. For comparison, one 18W fluorescent tube has about 1100 lumens but it is omnidirectional so some of it is wasted, even with a mirror.

Parts list, for a total of about $120, but which can be reduced with better planning (see notes):

  • 2 x Neutral White Rebel Tri-Star. These are aluminum bases, each with three Rebel LEDs premounted. They run at 9.45V, 700mA and some heatsinking is required to dissipate the ~6.5W of heat. Two bridges must be soldered on the pad to put the LEDs in series. Important: solder the bridges and two long power leads before attaching to the CPU heatsinks, or you'll have a very hard time because the solder will "freeze" on contact with that much heat-absorbing power - $37 (I chose the 480 lumen ones because the 540 were delayed)
  • Pre-cut adhesive thermal tape - $7.49. This will be used to stick the tri-star bases to heatsinks without messy grease or screws. Or you can drill into the CPU heatsink and use the grease that it came with.
  • A 21-30V power supply, such as a laptop adapter. There are many on Ebay for under $15 dollars. I got the 90W universal adapter from this seller to run at 24V. 90W is overkill but can feed a few such lighting systems with it - $14
  • BuckPuck 700mA driver with external dimming control helps ensure a long life and optimal light output for your LEDs by driving them exactly at 700mA. Without it you may shorten their life, as with a mere 0.2V increase over spec the current goes to 1A. See the pdf for wiring diagrams. Dimming is achieved with high-frequency pulse-width modulation (PWM) - $18.95
  • 220uF electrolitic capacitor is recommended in the BuckPuck diagrams when using long power wires - $1
  • 5K potentiometer for dimming ability.

  • 2 x ThermalTake AM2 CPU Cooler (CL-P0444). The heatsink in this package fits the acrylic cover internal shape best (dimensions 92 x 88.6 x 74.5mm). These come with thermal grease but since I had bought the thermal tape already, I took it off with a towel and alcohol. They are sufficient to cool the LEDs in open air without the fan. Old style, on sale at Fry's, and get two free fans for something else - $25
  • AOC single-slot fan. It is very quiet and does not clog with dust as easily as normal fans, and has the exact width to fit in the acrylic cover to blow directly through the heatsinks. A few slots may need to be cut in the external hood for cool air intake - $6
  • 12V power supply for fan. Any will do since the fan only takes 150mA or so - $10
  • A couple bright blue LEDs for moonlight, to run on above fan power supply (with an appropriate resistor) if always on. Why not.
  • A four-conductor cable (for power), 18ga wire for LEDs, soldering iron, solder, drill, dremel for slot cutting in the hood, fan filter, power jacks. Use different plugs to avoid mixing them, and do not have them under the hood to avoid water damage from condensation.
The 12V supply is always plugged in. It is so because the moonlights run off it and because I use the fan to avoid heavy condensation under the hood, so the food in the fish feeder inside does not get moldy. The 24V supply powering the lighting is on a timer.

This is what it looks like. The coverage is less uniform (more fall-off at edges) than the fluorescent, and the light cone can be made out somewhat, although in real life looks less pronounced than in the photo.


Thoughts in hindsight:
  1. The CPU heatsinks are now overkill with the fan running. An aluminum sheet would have been good enough. On the other hand, now the LEDs have some protection from a fan failure. Without the fan, the heatsinks reached 30C over room temp (so ~55C) in that enclosed space, so I suppose 70C at the LED base, which won't kill them but shortens their life and light output (see Rebel spec for luminous flux vs pad temperature).
  2. Would have preferred an U-shaped long heatsink with all the LEDs on the inside surrounded by the fins pointing out, but CPU ones are more readily available.
  3. Can probably run the fan at 9V, don't need that much flow.
  4. I think three tri-stars would fit this tank better (maybe next round?) would need 30V power supply or a second BuckPuck.
  5. The light level is maybe on par with the original Eclipse setup but is barely half of the 65W PC retrofit I was using before. There is room to install four tri-stars but a second BuckPuck is needed, which can run in parallel on the same 90W 24V power supply. The fan is then required.
  6. Some spacers under the front-facing sides of the heatsinks angle the LEDs more towards the back, so less light falls on the front glass.
  7. The dual power supply is probably cheapest, but running off a single supply (24V) is nicer. Either DC-DC or 2-5W resistors can be used to drop the voltage for the fan and LEDs, and a DC timer needs to be sourced to replace the external AC timer, for a truely self-contained solution. TODO: check if an AC digital timer can be easily modified to run on DC (has to be using DC internally).
  8. If one doesn't care to have a clean top hood, one could run a heat pipe or have the heatsinks protrude through the hood, or even fold a long aluminum sheet through a slot, all to dissipate heat in the room without the need for a fan, for an ultra-quiet system
  9. LEDs are very bright ("Class 2 device", do not look at them directly), a way to automatically dim them when opening the hood would be nice.
Wiring backside view. The fan slot with the filter is sealed off with some foam board because I cut slots in the hood to let air in from outside. The Luxeon wiring follows the BuckPuck diagram (the two tri-stars are in series) fed from the 24V source. The second circuit has three blue LEDs and a resistor in series on the 12V source. The fan is also on the 12V source in parallel with the moonlights.