Authoring a DVD with DVDAuthor

I intend to transfer family films from VHS to DVD, and VHS tapes that I bought, too. I previously recorded a big video file from the VHS and split this video into several parts. The time has come to make a DVD out of these parts.

For this article, I consider this real-world situation:

  • I have files 1.1.mpeg, 1.2.mpeg, 1.3.mpeg, 1.4.mpeg, 2.1.mpeg, …, 2.4.mpeg, … 6.4.mpeg. You get it: six films, each split into four parts, which accounts to 24 video files just for the films. Each part is small enough that I won’t need to define chapters.
  • I also have additional films: legal.mpeg (“This video is protected; if you watch it, you go to prison” kind of stuff…), ads.mpeg (guess…), and end.mpeg (“created by…, with the participation of…”).
  • I also recorded title.mpeg, which is a small part of the original big video file, suitable for looping and putting some buttons on it (“See all” and “Chapters”).
  • Finally, I created a 10-second static video without sound as a tribute to the open-source tools that were used to create the DVD; I named it thanks.mpeg.

legal, ads, thanks, leading to title, leading to “play all” (from 1.1 to end) or menu1-6, each giving access to X.1-4My plan is to have legal, then ads, then thanks, then the title menu. From there, I can either view all starting from 1.1, or enter menu1. Any menu[N] lets me view either one of N.1, N.2, N.3, or N.4, or go back to menu[N−1] (or title in the case of menu1), or forward to menu[N+1] (or title in the case of menu6). 1.4 is followed by 2.1, and so on until 3.4 being followed by 4.1; finally 4.4 is followed by end, which is followed by either title or a menu, as the technology permits… (either solution suits me).

One can see that I already have all the parts, except menu1 to menu6. Thus my first task is to prepare these videos. I decided to do something I have always wanted to try: have each of the four buttons leading to N.1, N.2, N.3, and N.4 be actual tiny videos, except low-frame-rate stop-motion will do because it is less work.

You have to know that each button in a DVD menu has three states: normal, highlighted, and selected; more over, all three states are expressed as three images, and the combination (in a very complex meaning of the word, explained here: http://floatinginspace.za.org/spumux/) of the images must use four colours only, transparent being one of these! Thus, there is a trick ;-) Indeed, tiny video-buttons cannot be created with four colours only.

A simple trick, really: the buttons must be drawn on the background video itself (remember: on a DVD, even a static image is always a video). Then the buttons are only simplistic overlays that give some focus or 3D effect. I will describe a simple way to do this kind of menu with Gimp, but someone with knowledge in shell scripts can do this way faster and more easily; I would know :-p

  1. I create a 720×576 (PAL format) menu background picture, with four plain white rectangles representing the four chapters’ videos. I also put on this picture a text object, with the title of the first series of videos.
  2. I open each video of the first series in turn in Avidemux, and save five significant frames of each video in JPEG format; thus I get 1.1.1.jpeg, 1.1.2.jpeg, …, 1.1.5.jpeg, 1.2.1.jpeg, …, 1.2.5.jpeg, 1.3.1.jpeg, …, 1.3.5.jpeg, 1.4.1.jpeg, … 1.4.5.jpeg.
  3. In Gimp, I resize 1.1.1.jpeg to 1.4.1.jpeg to the size of the place-holders I left on the menu picture, and put these thumbnails in place of the plain white rectangles; I export this image to 1.1.png. Then I resize 1.1.2.jpeg to 1.4.2.jpeg to the size of the place-holders, and replace the thumbnails, and export this image to 1.2.png. And so on until I export 1.5.png based on the frames 1.1.5.jpeg to 1.4.5.jpeg.
  4. Using FFMpeg, I create the video, actually a succession of five still images with a duration of 2 seconds for each, that is a frame-rate of ½ FPS. I should only have to “cat” the five images to “ffmpeg”, but for some reason the first image is ignored, which is why I actually give this one twice:
    cat 1.1.png 1.?.png | ffmpeg -f image2pipe -vcodec png -r 1/2 -i - -target pal-dvd -vcodec mpeg2video -an menu1.mpeg
    I did not put sound, but you can if you want…
  5. I start again steps 2 to 4, with the videos of the second series, then the third, and so on until the sixth, not forgetting to change the title of the series each time.

Now I have all the videos I need. I could use DVDStyler, the best authoring tool from the few I have tried. But I want to control the whole process, so instead I choose the DVDAuthor suite, on which DVDStyler is based.

First I have to create the actual menus, that is videos with buttons on them, or more precisely video-container (MPEG) files with buttons “muxed” into them. It happens that buttons are nothing more than mandatory subtitles, where a DVD is concerned, and subtitles nothing more than images. There are a few subtleties, though:

  • I can only use four colours for these images.
  • All three states (normal, highlighted, and selected) of the buttons are actually merged, leading to a complicated way to count colors.

I start with the menuN buttons; they’re all the same: one button for title, one button for menu[N-1], and one for menu[N+1], each being a simple frame and a text, plus a frame only for the videos. Here’s the result:

  • normal state: DVD menu mask (normal state) for spumux
  • highlighted state: DVD menu mask (highlighted state) for spumux
  • selected state: DVD menu mask (selected state) for spumux

Then I create the menu.xml file that will tell “spumux” where the buttons are and how they should be named:

<subpictures format="PAL">
<stream>
<spu start="00:00:00.00" force="yes"
image="chap_image.png"
highlight="chap_highlight.png"
select="chap_select.png">
<button name="title" x0="364" y0="52" x1="502" y1="118"
up="avant" left="1" down="1" right="4"/>
<button name="1" x0="74" y0="316" x1="186" y1="402"
up="menu" left="prev" down="avant" right="2"/>
<button name="2" x0="228" y0="316" x1="338" y1="402"
up="menu" left="1" down="avant" right="3"/>
<button name="3" x0="382" y0="316" x1="490" y1="402"
up="menu" left="2" down="apres" right="4"/>
<button name="4" x0="536" y0="316" x1="644" y1="402"
up="menu" left="3" down="apres" right="suiv"/>
<button name="before" x0="198" y0="444" x1="336" y1="510"
up="1" left="apres" down="menu" right="apres"/>
<button name="after" x0="382" y0="444" x1="520" y1="510"
up="4" left="avant" down="menu" right="avant"/>
<button name="previous" x0="14" y0="316" x1="46" y1="402"
up="menu" left="suiv" down="avant" right="1"/>
<button name="next" x0="672" y0="316" x1="702" y1="402"
up="menu" left="4" down="apres" right="prev"/>
<action name="previous" x0="14" y0="316" x1="46" y1="402"/>
<action name="next" x0="672" y0="316" x1="702" y1="402"/>
</spu>
</stream>
</subpictures>

Actually, I could not find how to make the action tag work, which should enable “auto-click” if I’m correct. But it doesn’t matter; I don’t need that. Now I use “spumux” to kind-of insert my buttons into the videos:

for m in 1 2 3 4 5 6; do
spumux -m dvd menu.xml <menu${m}.mpeg >menu${m}_mux.mpeg
done

To create the title menu, I let “spumux” infer the location of the buttons and the required navigation. The buttons are thus named “1” (view all) and “2” (chapters). Here’s title.xml, followed by the command I run:

<subpictures format="PAL">
<stream>
<spu start="00:00:00.00" force="yes" autooutline="infer"
image="title_image.png"
highlight="title_highlight.png"
select="title_select.png"/>
</stream>
</subpictures>

spumux -m dvd title.xml <title.mpeg >title_mux.mpeg

The preparation is finally done. Now I have to package all of this into an actual DVD. To do that, I create this dvdauthor.xml file; it’s not an easy task because the documentation is sparse on what is allowed and what is not…; but I got some inspiration from DVDStyler ;-)

<?xml version="1.0" encoding="utf-8"?>
<dvdauthor jumppad="0" dest="/home/tYY/AV-data/dvd/" format="pal">
<vmgm>
<menus>
<video format="pal" aspect="4:3"/>
<audio lang="FR"/>
<!--************** VMGM **************-->
<pgc>
<vob file="/usr/share/dvdstyler/data/empty_pal_mp2.mpg"/>
<pre>g1 = 1; jump titleset 1 menu;</pre>
</pgc>
</menus>
</vmgm>
<titleset>
<menus>
<video format="pal" aspect="4:3" resolution="720x576"/>
<audio lang="FR"/>
<!--************** TITLE **************-->
<pgc entry="root">
<vob file="/home/tYY/AV-data/title_mux.mpeg" pause="2"/>
<button name="1">g2 = 1; g0 = 9216; jump titleset 2 menu;</button>
<button name="2">g2 = 0; g0 = 9216; jump titleset 2 menu;</button>
<pre>if ( g1 == 1 ) { g1 = 0; jump title 1; }</pre>
<post>jump cell 1;</post>
</pgc>
</menus>
<titles>
<video format="pal" aspect="4:3" resolution="720x576"/>
<audio lang="FR"/>
<!--************** LEGAL **************-->
<pgc>
<vob file="/home/tYY/AV-data/legal.mpeg"/>
<post>jump title 2;</post>
</pgc>
<!--************** ADS **************-->
<pgc>
<vob file="/home/tYY/AV-data/ads.mpeg"/>
<post>jump title 3;</post>
</pgc>
<!--************** THANKS **************-->
<pgc>
<vob file="/home/tYY/AV-data/thanks.mpeg"/>
<post>call menu;</post>
</pgc>
</titles>
</titleset>
<titleset>
<menus>
<video format="pal" aspect="4:3" resolution="720x576"/>
<audio lang="FR"/>
<!--************** MENU 1 **************-->
<pgc entry="root">
<vob file="/home/tYY/AV-data/menu1_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">jump titleset 1 menu;</button>
<button name="1">g0 = button; jump title 1;</button>
<button name="2">g0 = button; jump title 2;</button>
<button name="3">g0 = button; jump title 3;</button>
<button name="4">g0 = button; jump title 4;</button>
<button name="next">g0 = 9216; jump menu 2;</button>
<button name="before">jump titleset 1 menu;</button>
<button name="after">g0 = 9216; jump menu 2;</button>
<pre>
if ( g2 == 2 ) { jump titleset 1 menu; }
if ( g2 == 1 ) { g2 = 2; jump title 1; }
button = g0;
</pre>
<post>jump cell 1;</post>
</pgc>
<!--************** MENU 2 **************-->
<pgc>
<vob file="/home/tYY/AV-data/menu2_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">g0 = 8192; jump menu 1;</button>
<button name="1">g0 = button; jump title 5;</button>
<button name="2">g0 = button; jump title 6;</button>
<button name="3">g0 = button; jump title 7;</button>
<button name="4">g0 = button; jump title 8;</button>
<button name="next">g0 = 9216; jump menu 3;</button>
<button name="before">g0 = 8192; jump menu 1;</button>
<button name="after">g0 = 9216; jump menu 3;</button>
<pre>button = g0;</pre>
<post>jump cell 1;</post>
</pgc>
<!--************** MENU 3 **************-->
<pgc>
<vob file="/home/tYY/AV-data/menu3_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">g0 = 8192; jump menu 2;</button>
<button name="1">g0 = button; jump title 9;</button>
<button name="2">g0 = button; jump title 10;</button>
<button name="3">g0 = button; jump title 11;</button>
<button name="4">g0 = button; jump title 12;</button>
<button name="next">g0 = 9216; jump menu 4;</button>
<button name="before">g0 = 8192; jump menu 2;</button>
<button name="after">g0 = 9216; jump menu 4;</button>
<pre>button = g0;</pre>
<post>jump cell 1;</post>
</pgc>
<!--************** MENU 4 **************-->
<pgc>
<vob file="/home/tYY/AV-data/menu4_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">g0 = 8192; jump menu 3;</button>
<button name="1">g0 = button; jump title 13;</button>
<button name="2">g0 = button; jump title 14;</button>
<button name="3">g0 = button; jump title 15;</button>
<button name="4">g0 = button; jump title 16;</button>
<button name="next">g0 = 9216; jump menu 5;</button>
<button name="before">g0 = 8192; jump menu 3;</button>
<button name="after">g0 = 9216; jump menu 5;</button>
<pre>button = g0;</pre>
<post>jump cell 1;</post>
</pgc>
<!--************** MENU 5 **************-->
<pgc>
<vob file="/home/tYY/AV-data/menu5_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">g0 = 8192; jump menu 4;</button>
<button name="1">g0 = button; jump title 17;</button>
<button name="2">g0 = button; jump title 18;</button>
<button name="3">g0 = button; jump title 19;</button>
<button name="4">g0 = button; jump title 20;</button>
<button name="next">g0 = 9216; jump menu 6;</button>
<button name="before">g0 = 8192; jump menu 4;</button>
<button name="after">g0 = 9216; jump menu 6;</button>
<pre>button = g0;</pre>
<post>jump cell 1;</post>
</pgc>
<!--************** MENU 6 **************-->
<pgc>
<vob file="/home/tYY/AV-data/menu6_mux.mpeg" pause="2"/>
<button name="title">jump titleset 1 menu;</button>
<button name="previous">g0 = 8192; jump menu 5;</button>
<button name="1">g0 = button; jump title 21;</button>
<button name="2">g0 = button; jump title 22;</button>
<button name="3">g0 = button; jump title 23;</button>
<button name="4">g0 = button; jump title 24;</button>
<button name="next">jump titleset 1 menu;</button>
<button name="before">g0 = 8192; jump menu 5;</button>
<button name="after">jump titleset 1 menu;</button>
<pre>button = g0;</pre>
<post>jump cell 1;</post>
</pgc>
</menus>
<titles>
<video format="pal" aspect="4:3" resolution="720x576"/>
<audio lang="FR"/>
<!--************** TITLE 1 **************-->
<pgc>
<vob file="/home/tYY/AV-data/1.1.mpeg"/>
<post>jump title 2;</post>
</pgc>
<!--************** TITLE 2 **************-->
<pgc>
<vob file="/home/tYY/AV-data/1.2.mpeg"/>
<post>jump title 3;</post>
</pgc>
<!--************** TITLE 3 **************-->
<pgc>
<vob file="/home/tYY/AV-data/1.3.mpeg"/>
<post>jump title 4;</post>
</pgc>
<!--************** TITLE 4 **************-->
<pgc>
<vob file="/home/tYY/AV-data/1.4.mpeg"/>
<post>jump title 5;</post>
</pgc>
<!--************** TITLE 5 **************-->
<pgc>
<vob file="/home/tYY/AV-data/2.1a.mpeg"/>
<post>jump title 6;</post>
</pgc>
<!--************** TITLE 6 **************-->
<pgc>
<vob file="/home/tYY/AV-data/2.2.mpeg"/>
<post>jump title 7;</post>
</pgc>
<!--************** TITLE 7 **************-->
<pgc>
<vob file="/home/tYY/AV-data/2.3.mpeg"/>
<post>jump title 8;</post>
</pgc>
<!--************** TITLE 8 **************-->
<pgc>
<vob file="/home/tYY/AV-data/2.4a.mpeg"/>
<post>jump title 9;</post>
</pgc>
<!--************** TITLE 9 **************-->
<pgc>
<vob file="/home/tYY/AV-data/3.1.mpeg"/>
<post>jump title 10;</post>
</pgc>
<!--************** TITLE 10 **************-->
<pgc>
<vob file="/home/tYY/AV-data/3.2.mpeg"/>
<post>jump title 11;</post>
</pgc>
<!--************** TITLE 11 **************-->
<pgc>
<vob file="/home/tYY/AV-data/3.3a.mpeg"/>
<post>jump title 12;</post>
</pgc>
<!--************** TITLE 12 **************-->
<pgc>
<vob file="/home/tYY/AV-data/3.4.mpeg"/>
<post>jump title 13;</post>
</pgc>
<!--************** TITLE 13 **************-->
<pgc>
<vob file="/home/tYY/AV-data/4.1.mpeg"/>
<post>jump title 14;</post>
</pgc>
<!--************** TITLE 14 **************-->
<pgc>
<vob file="/home/tYY/AV-data/4.2a.mpeg"/>
<post>jump title 15;</post>
</pgc>
<!--************** TITLE 15 **************-->
<pgc>
<vob file="/home/tYY/AV-data/4.3.mpeg"/>
<post>jump title 16;</post>
</pgc>
<!--************** TITLE 16 **************-->
<pgc>
<vob file="/home/tYY/AV-data/4.4.mpeg"/>
<post>jump title 17;</post>
</pgc>
<!--************** TITLE 17 **************-->
<pgc>
<vob file="/home/tYY/AV-data/5.1.mpeg"/>
<post>jump title 18;</post>
</pgc>
<!--************** TITLE 18 **************-->
<pgc>
<vob file="/home/tYY/AV-data/5.2.mpeg"/>
<post>jump title 19;</post>
</pgc>
<!--************** TITLE 19 **************-->
<pgc>
<vob file="/home/tYY/AV-data/5.3a.mpeg"/>
<post>jump title 20;</post>
</pgc>
<!--************** TITLE 20 **************-->
<pgc>
<vob file="/home/tYY/AV-data/5.4a.mpeg"/>
<post>jump title 21;</post>
</pgc>
<!--************** TITLE 21 **************-->
<pgc>
<vob file="/home/tYY/AV-data/6.1.mpeg"/>
<post>jump title 22;</post>
</pgc>
<!--************** TITLE 22 **************-->
<pgc>
<vob file="/home/tYY/AV-data/6.2a.mpeg"/>
<post>jump title 23;</post>
</pgc>
<!--************** TITLE 23 **************-->
<pgc>
<vob file="/home/tYY/AV-data/6.3.mpeg"/>
<post>jump title 24;</post>
</pgc>
<!--************** TITLE 24 **************-->
<pgc>
<vob file="/home/tYY/AV-data/6.4a.mpeg"/>
<post>jump title 25;</post>
</pgc>
<!--************** TITLE 25 **************-->
<pgc>
<vob file="/home/tYY/AV-data/end.mpeg"/>
<post>call menu;</post>
</pgc>
</titles>
</titleset>
</dvdauthor>

This file tells how all my video files are organized, and linked to each other. In short, this is the translation of the illustration I put at the start of this article.

Now, you may wonder why some videos have a “a” in their file-names, whereas no such “a” was mentioned before. This is because I encountered a bug related to the order in which video and audio are present in the MPEG container; this bug is clearly on DVDAuthor’s side (the order should not matter), but it seems to be triggered by FFMpeg. Here’s (an excerpt of) DVDAuthor’s output with the original 2.1.mpeg file for example:


STAT: Processing /home/tYY/AV-data/1.3.mpeg...
WARN: Video PTS does not line up on a multiple of a field.

INFO: Video pts = 0.500 .. 73.554
INFO: Audio[8] pts = 0.506 .. 73.538

STAT: Processing /home/tYY/AV-data/1.4.mpeg...
STAT: VOBU 383 at 138MB, 25 PGCs
INFO: Video pts = 0.184 .. 18.864
INFO: Audio[8] pts = 0.184 .. 18.616

STAT: Processing /home/tYY/AV-data/2.1.mpeg...
ERR: Cannot infer pts for VOBU if there is no audio or video and it is the
ERR: first VOBU.

Thankfully, there is a lossless solution to this problem: I open the 2.1.mpeg file in Avidemux, choose “copy” for both the audio and video codecs, MPEG-PS for the container format, configured for DVD muxing, and save the video as 2.1a.mpeg. I do that for each video where DVDAuthor has this problem. Of course, I reflect these changes into the dvdauthor.xml file, hence the occasional “a” characters.

If all went well, there only remains to run the following commands (assuming a blank DVD is in the /dev/sr0 device) to obtain a DVD that can be played by any DVD player:

# use dvdauthor to create the dvd structure
# in /home/tYY/AV-data/dvd
dvdauthor -x dvdauthor.xml

# use mkisofs to create /home/tYY/my-dvd.iso
# from this DVD structure
mkisofs -V "My example DVD" -o /home/tYY/my-dvd.iso -dvd-video /home/tYY/AV-data/dvd

# use growisofs to burn /home/tYY/my-dvd.iso
growisofs -dvd-compat -Z /dev/sr0=/home/tYY/my-dvd.iso -use-the-force-luke=dao

Here are some old but useful links about DVD authoring and DVD burning:

That is all. I did not think I would write such a long article but there was so much to tell!

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

La discussion continue ailleurs

URL de rétrolien : http://yalis.fr/cms/index.php/trackback/17

Fil des commentaires de ce billet