I have recently come into possession of a bunch of xvids that I would like to watch on a DVD player (mainly so I can show my aunt). Since this is my first real foray into the wonderful and incredibly overcomplicated world of DVD video I thought I'd automate everything. Well, that and the amount of time everything takes making it an overnight job...

The first step is to recode the file into MPEG-2 so that a DVD player can understand it. While we're doing this, grab a screenshot for the menu.

if [ -z "$1" ]; then
    echo "Please tell me what to recode."
fi

fn=`basename "$1" .avi`

# Convert the file to MPEG-2 for the DVD
if [ ! -f "$fn".m2v ]; then
    transcode -i "$fn".avi -y ffmpeg --export_prof dvd-pal --export_asr 3 \
        -o "$fn" -D0 -b224 -N 0x2000 -s2 -m "$fn".ac3 -J modfps=clonetype=3 \
        --export_fps 25 -w 1800
fi

if [ ! -f "$fn".mpg ]; then
    mplex -f 8 -o "$fn".mpg "$fn".m2v "$fn".ac3
fi

# Extract a screenshot for the menu
ffmpeg -y -i "$fn".mpg -vframes 1 -ss 00:00:05 -an -vcodec png -f rawvideo -s 224x126 "$fn".png

Of course, we need to do this over a whole bunch of files (six of them in the current implementation) and then finish the menu and prepare dvdauthor's input.

labelfilter='s/Series - S..E\(..\) - \(.*\)/\1: \2/'
background=lightgray
title='DVD title'

i=0

# Convert each avi and label the screenshots for the menu
for f in "$@"; do
    fn=`basename "$f" .avi`
    label=`echo $fn | sed "$labelfilter"`
    label=${label##0}
    echo $label
    i=$(($i+1))
    mkmoviepart.sh "$f"
    montage -pointsize 16 -background transparent -label "$label" "$fn".png \
        -geometry "1x1+0+0<" menu_$i.png
done

# Assemble images into menu background
convert -size 720x576 -density 75x80 xc:$background -pointsize 50 \
    -draw "gravity Center text 0,-220 '$title'" \
    -draw "image over  12,150 0,0 'menu_1.png'" \
    -draw "image over 248,150 0,0 'menu_2.png'" \
    -draw "image over 484,150 0,0 'menu_3.png'" \
    -draw "image over  12,360 0,0 'menu_4.png'" \
    -draw "image over 248,360 0,0 'menu_5.png'" \
    -draw "image over 484,360 0,0 'menu_6.png'" \
    menu.jpg

# Build the rest of the menu
function mkframes() {
    colour=$1
    name=$2
    convert -size 720x576 -density 75x80 xc:transparent \
        -stroke $colour -strokewidth 4 -fill transparent \
        -draw "rectangle  12,150 236,276" \
        -draw "rectangle 248,150 472,276" \
        -draw "rectangle 484,150 708,276" \
        -draw "rectangle  12,360 236,486" \
        -draw "rectangle 248,360 472,486" \
        -draw "rectangle 484,360 708,486" \
        $name.png
}

mkframes yellow menu_select
mkframes red menu_highlight

convert menu.jpg ppm:- | ppmtoy4m -n50 -F25:1 -A59:54 -I p -r -S 420mpeg2 \
    | mpeg2enc -n p -f8 -b5000 -a2 -o menu.m2v

ffmpeg -ab 224 -ar 48000 -ac 2 -t 5 menu_audio.ac3

mplex -f 8 -o menu.mpg menu.m2v menu_audio.ac3

cat <<EOT > menu.xml
<subpictures>
  <stream>
    <spu start="00:00:00.0" end="00:00:00.0"
         highlight="menu_highlight.png"
         select="menu_select.png"
         autooutline="infer"
         autoorder="rows"/>
  </stream>
</subpictures>
EOT

spumux menu.xml < menu.mpg > dvd_menu.mpg

# Feed dvdauthor its dinner
echo "<dvdauthor dest=\"${dvddir}\">" > dvd.xml
cat <<EOT >> dvd.xml
  <vmgm/>
  <titleset>
    <menus>
      <video widescreen="nopanscan" />
      <pgc>
        <button> jump title 1; </button>
        <button> jump title 2; </button>
        <button> jump title 3; </button>
        <button> jump title 4; </button>
        <button> jump title 5; </button>
        <button> jump title 6; </button>
        <vob file="dvd_menu.mpg"/>
        <post> jump cell 1; </post>
      </pgc>
    </menus>
    <titles>
      <video widescreen="nopanscan" />
EOT

for f in "$@"; do
    fn=`basename "$f" .avi`
    echo '      <pgc>' >> dvd.xml
    echo '        <post> call menu; </post>' >> dvd.xml
    echo -n '        <vob file="' >> dvd.xml
    echo -n "$fn.mpg" >> dvd.xml
    echo '" chapters="0,5:00,10:00,15:00,20:00,25:00,30:00,35:00,40:00"/>' >> dvd.xml
    echo '      </pgc>' >> dvd.xml
done

cat <<EOT >> dvd.xml
    </titles>
  </titleset>
</dvdauthor>
EOT

Thanks muchly to shiznix and the Gentoo forums for pointing me in several of the right directions.