Subtitles, are, of course, the most time consuming of the two things on the list. Make sure you schedule at least 4 times as much as the running time of the material (which for the typical movie means an entire working day) and feel free to follow these simple instructions:
- Prepare a transcript for the video in the native language using a SubRip format. I like it for simplicity it is just a text file with a very simple structure and it is also supported by 99% of the A/V tools. You can use any of the Free Software applications that are specifically designed for this purpose: GTK based Subtitleeditor and Java based Jubler come readily to mind. Or you can simply start MPlayer and record timestamps by hand. Whatever works for you.
- Now that you have your sub.srt file make sure that the timings
in native language are reasonable. How much lag there has to be between
something happening in the video/audio track and your subtitles is
a matter of personal choice. Just make sure you are comfortable
with it:
$ mplayer -sub sub.srt -font ~/.fonts/Arial.ttf video.mpeg -
It turns out that MPlayer is pretty liberal as far as glitches
and bugs in subtitle file go. It is a good idea to at least check
the file for timestamps being monotonous:
$ grep -- "-->" sub.srt | tr -d ':,' | sed -e 's#-->#\n#' |\ awk 'BEGIN { d=0; } { if ($0<d) { print $0 "<" d; } else { d=$0; } }' - Translation into English is next. Make sure that you don't go overboard with it though. Each subtitle should not be longer than 50 characters (80 characters max) and the duration for each of them shouldn't be smaller than 25 characters per minute.
Movies run 24 frames per second, PAL runs at 25. All in all it is not that much of a strech really, although a dreaded PAL speedup issue will crop up and it'll make us fiddle with the audio track. Actually, in our case it'll be more appropriate to call it a "PAL slowdown" issue and the only reason I'm trading audio fidelity for video fidelity here is because the audio track is in a foreign language to begin with. Now, assuming that your original material is coming from a PAL DVD here's what it takes to: deinterlace its VOBs, scale them to fit an NTSC resolution and encode all that into a 2:3 pulldown flagged MPEG2:
$ ffmpeg -i <(cat *.VOB) -f yuv4mpegpipe - |\
yuvdeinterlace | yuvscaler -M BICUBIC -O SIZE_720x480 |\
mpeg2enc -n n -f 8 -F 4 -a 2 -p -o /tmp/pal_slowdown.mpeg
Once again -- the trick here is that we DO NOT change the framerate
by interpolating missing fields. We are encoding the NTSC DVD using
a Telecine Process
as though the original was a movie reel.
Well, now that the movie got 25/24 (4.166%) longer we have to rescale the audio track as well. Fortunately, the jack of all trades in the audio kingdom -- Audacity has a special filter just for that. It is called Change tempo and it usually works pretty well:
$ ffmpeg -i <(cat *.VOB) /tmp/audio.wav
$ audacity /tmp/audio.wav # apply "Change tempo"
$ ffmpeg -i /tmp/audio.wav -ab 128000 /tmp/audio.mp2
$ rm /tmp/audio.wav
Now all that left for you to do is to multiplex the new audio track
from the freshly minted /tmp/audio.mp2 and the newly encoded
MPEG2 from /tmp/pal_slowdown.mpeg into the, still subtitleless, MPEG2
stream /tmp/nosubs.mpeg:
$ mplex -f8 -o /tmp/nosubs.mpeg /tmp/pal_slowdown.mpeg /tmp/audio.mp2
Ok, it seems like all we have left to do at this point is to multiplex
subtitles into the MPEG2 stream and enjoy an NTSC DVD in its full glory.
Well, there's a catch -- we have to stretch subtitles in the same way
we stretched audio track: all timestamps have to be multiplied by
1.043:
cat sub.srt | awk ' \
function fwd(t) { split(t, ar, ":");
split(ar[3], arr, ",");
ar[3]=arr[1]; ar[4]=arr[2];
return ar[1]*60*60*1000+
ar[2]*60*1000+
ar[3]*1000+
ar[4];
}
function rev(ts) { ts=ts/1000;
printf("%02d:%02d:%02d,%03d",
(ts/(60*60*1000))%24,
(ts/(60*1000))%60,
(ts/1000)%60, ts%1000);
}
/-->/ { rev(fwd($1)*1043);
printf " --> " ;
rev(fwd($3)*1043);
print "";
next;
}
{ print $0; }' > slowed_down.srt
Done. Next step -- embedding subtitles into an MPEG2 stream. We are going
to do this in style, though. We don't want to simply permanently burn
the image of subtitles onto each frame. We want them to behave like they
do on commercial DVDs: be switchable on/off from the remote control and
also be "on" by default. Fortunately, the tool from a dvdauthor package
called spumux is exactly the right tool for the job. Now in order for
it to work we have to give it an XML configuration file and also store
an appropriate TTF font in a ~/.spumux subdirectory (I like Bitstream's
Vera -- it looks nice and it is free):
$ cp ~/.fonts/Vera.ttf ~/.spumux/
$ cat spumux.xml
<subpictures>
<stream>
<textsub filename="slowed_down.srt" characterset="ISO8859-1"
fontsize="25.0" font="Vera.ttf"
horizontal-alignment="center"
vertical-alignment="bottom"
left-margin="60" right-margin="60"
top-margin="20" bottom-margin="30" subtitle-fps="30"
movie-fps="30" movie-width="720" movie-height="480"
/>
</stream>
</subpictures>
$ spumux -P spumux.xml < /tmp/nosubs.mpeg > final.mpeg
We're almost done. The very last step is to author a DVD content with a dvdauthor
utility and create an ISO image. Just as spumux, dvdauthor needs an XML
configuration file and since we wanted our subtitles to be on by default
we have to instruct it to write into the register of the DVDs virtual machine
(yep, DVDs are just like Java -- they have a virtual machine). That's
what that weird looking subtitle=64; is there for:
$ cat dvd.xml
<dvdauthor>
<vmgm />
<titleset>
<titles>
<pgc>
<pre> subtitle=64; </pre>
<vob file="final.mpeg" />
</pgc>
</titles>
</titleset>
</dvdauthor>
$ dvdauthor -o dvd -x dvd.xml
$ mkisofs -dvd-video -udf -o dvd.iso -V RomanProductions ./dvd
Done! Go ahead, burn a bunch of DVD-R and start introducing your
American friends into the wonderful world of totally foreign
things.
linux(1)> grep -- "-->" sub.srt | tr -d ':,' | sed -e 's#-->#\#' |\ awk 'BEGIN { d=0; } { if ($0linux(2)> ffmpeg -i <(cat *.VOB) -f yuv4mpegpipe - |\ yuvdeinterlace | yuvscaler -M BICUBIC -O SIZE_720x480 |\ mpeg2enc -n n -f 8 -F 4 -a 2 -p -o /tmp/pal_slowdown.mpeg linux(3)> ffmpeg -i <(cat *.VOB) /tmp/audio.wav linux(4)> audacity /tmp/audio.wav # apply "Change tempo" linux(5)> ffmpeg -i /tmp/audio.wav -ab 128000 /tmp/audio.mp2 linux(6)> rm /tmp/audio.wav linux(7)> mplex -f 8 -o /tmp/nosubs.mpeg /tmp/pal_slowdown.mpeg /tmp/audio.mp2 linux(8)> cat sub.srt | awk ' \ function fwd(t) { split(t, ar, ":"); split(ar[3], arr, ","); ar[3]=arr[1]; ar[4]=arr[2]; return ar[1]*60*60*1000+ar[2]*60*1000+ar[3]*1000+ar[4]; } function rev(ts) { ts=ts/1000; printf("%02d:%02d:%02d,%03d", (ts/(60*60*1000))%24, (ts/(60*1000))%60, (ts/1000)%60, ts%1000); } /-->/ { rev(fwd($1)*1043); printf " --> " ; rev(fwd($3)*1043); print ""; next; } { print $0; }' > slowed_down.srt linux(9)> cp ~/.fonts/Vera.ttf ~/.spumux/ linux(10)> cat spumux.xml <subpictures> <stream> <textsub filename="slowed_down.srt" characterset="ISO8859-1" fontsize="25.0" font="Vera.ttf" horizontal-alignment="center" vertical-alignment="bottom" left-margin="60" right-margin="60" top-margin="20" bottom-margin="30" subtitle-fps="30" movie-fps="30" movie-width="720" movie-height="480" /> </stream> </subpictures> linux(11)> spumux -P spumux.xml < /tmp/nosubs.mpeg > final.mpeg linux(12)> cat dvd.xml <dvdauthor> <vmgm /> <titleset> <titles> <pgc> <pre> subtitle=64; </pre> <vob file="final.mpeg" /> </pgc> </titles> </titleset> </dvdauthor> linux(13)> dvdauthor -o dvd -x dvd.xml linux(14)> mkisofs -dvd-video -udf -o dvd.iso -V RomanProductions ./dvd