logo
Transcoding Divx to VCD, SVCD, CVCD, etc. under Linux

by paranouei

LinuxMalaga

News(02/12/2004): New script for encoding to KVCD, check this thread, the link to the script is at the bottom

News(06/09/2003): New script divx2cvcd available. This new script doesn't use transcode anymore so now supports more codecs and its more customizable.

News(20/01/2003): New forum available. You can ask there your questions about this guide.

So you just came from shopping with your brand new DVD player, and now you would like to transcode your Divx files to VCD to enjoy them in your big TV at the living room...

This task can be done in linux, you can even automate it so you just have to type i.e. divx2vcd <file.avi>, go for a walk, and when you are back you have a fresh .bin and .cue files ready to burn.

Ok, let's see a few basic concepts before we begin:


Basic concepts:

  • VCD: Video CD. It's an MPEG-1 stream, at 352x288 and 25 fps (PAL), or 352x240 and 29.976 fps (NTSC). It has constat bitrate at 1150kbps and the audio is MPEG layer 2 at 224 kbps. You can fit as many minutes as the CD says (74 or 80).

  • SVCD: Super Video CD. It's an MPEG-2 stream, at 480x576 and 25 fps (PAL), or 480x480 and 29.976 fps (NTSC). The bitrate may be variable up to 2600kbps, and the audio can be between 32 and 384 kbps. Depending on the bitrate you choose you can fit more or less minutes, but you can usually fit between 40 and 55 minutes per CD.

  • XVCD, CVCD..: These are modifications of the standard, with different bitrates, etc., and they could not work on all DVDs. But today's DVD players can play almost everything.

    For instance, CVCD is just a VCD with variable bitrate. This way, "easy" scenes take a lower bitrate
    so you have more space left and you can fit more minutes. You can fit this way more than 90 minutes in a CD.



Tools:
  • Mplayer. This will be our input filter for transcode. This way, transcode will be able to handle everthing mplayer can read (divx, realmedia, subtitles...)

  • Transcode. This is the main tool. It's for transcoding between almost any imaginable format.

  • MJPEG Tools. This will be our output filter. Also, in includes tools for multiplexing the mpg.

  • VCDImager. This tool is for creating the .bin and .cue files from the mpg.

Also, my scripts use some basic utils like bc (calculator) and perl.

Well, once you've got that, let's start ;)


Divx2VCD:

I wrote the following script "divx2vcd", it takes care of the calculations to get an image with the same aspect ratio (adding black borders if needed). It uses constant, so it's fully VCD standard. The maximum file size (to make them fit in a CD), it's in CDSIZE variable. The script creates the video and audio with transcode, then it multiplexes them with mplex, and finally it creates de images. You can download it from here. I'm gonna paste it here so you can see it (sorry comments are in spanish):

-- Inicio divx2vcd --


#!/bin/bash

# Este script pasa un Divx a VCD. Para los archivos temporales se
# necesita al menos 4.5 Gigas (m1v y mpa, los .mpg y los .bin)

DIR=`pwd`
TEMPFOLDER=/tmp/divx2vcd-$RANDOM
TEMP_TEMPLATE=/tmp/tcmplex-template-$RANDOM

# CDSIZE Values. VCDs are write in Mode 2, so the filesizes are the
# the following:
# 74 Min/650Mb ---> CDSIZE=735
# 80 Min/700Mb ---> CDSIZE=795
CDSIZE=795
#VIDEORATE=1150
AUDIORATE=224

if [ $# -eq 0 ]; then
echo "Usage:"
echo " divx2vcd <divxfile>"
exit 1
fi

FILE=$1
if [ "$1" == "`basename \"$1\"`" ]; then
FILE="$DIR/$1"
fi

mkdir $TEMPFOLDER
cd $TEMPFOLDER

tcprobe -i "$FILE" > $TEMPFOLDER/info

WIDTH=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /width=(\d+)/ ; print $1' `
HEIGHT=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /height=(\d+)/ ; print $1' `
FPS=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /V: (.+?) fps/ ; print $1' `
FPS_1=`echo "scale=1 ; $FPS/1"| bc -l`
FRAMES=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /frames=(\d+)/ ; print $1' `
SEGUNDOS_TOTAL=`echo "scale=0 ; ($FRAMES / $FPS)"| bc -l`
HORAS=`echo "scale=0 ; ($SEGUNDOS_TOTAL / 3600)"| bc -l`
MINUTOS=`echo "scale=0 ; (($SEGUNDOS_TOTAL - 3600 * $HORAS)/60)"| \
bc -l`
SEGUNDOS=`echo "scale=0 ; ($SEGUNDOS_TOTAL % 60)"| bc -l`

echo "*************** FILE INFO ***************"
echo "Frame Size: ${WIDTH}x${HEIGHT} - FPS: $FPS"
echo "Length: $FRAMES - Seconds: $SEGUNDOS_TOTAL"
echo "$HORAS hours, $MINUTOS minutes, $SEGUNDOS seconds"

if [ $FPS_1 == "29.9" -o $FPS_1 == "30" -o $FPS_1 == "23.9" ]; then
WIDTH_OUT=352
HEIGHT_OUT=240
else
WIDTH_OUT=352
HEIGHT_OUT=288
fi

echo "Video Output: ${WIDTH_OUT}x${HEIGHT_OUT}"

# Ahora calculamos los valores pa los bordes.

ANCHO_1_1_OUT=`echo "($HEIGHT_OUT * 4/3)"| bc -l`
ALTO_OUT=`echo "$HEIGHT / ($WIDTH / $ANCHO_1_1_OUT)" | bc -l`
# Redondeamos
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT/1"| bc -l`
# Nos aseguramos de que sea par
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT+$ALTO_OUT%2" | bc -l`

BORDE=`echo "scale=0 ; ($HEIGHT_OUT-$ALTO_OUT)/2"| bc -l`
echo "alto sin bordes: $ALTO_OUT, con borde: $BORDE"

# Borramos Pelicula.m1v y Pelicula.mpa
rm -f Pelicula.m1v Pelicula.mpa


cd $TEMPFOLDER

echo "transcode -i \"$FILE\" -V -x mplayer -y mpeg2enc,mp2enc \
-F 1 -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula"
transcode -i "$FILE" -V -x mplayer -y mpeg2enc,mp2enc \
-F 1 -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula


rm $TEMPFOLDER/*
rmdir $TEMPFOLDER

cd $DIR

# Si no hay Pelicula.m1v y Pelicula.mpa salir
[ -f Pelicula.m1v -a -f Pelicula.mpa ] || exit 1

rm -f Pelicula*.mpg

#Ahora multiplexamos el .mpg
echo "maxFileSize = $CDSIZE" > $TEMP_TEMPLATE
tcmplex -i Pelicula.m1v -p Pelicula.mpa -o Pelicula.mpg \
-m 1 -F $TEMP_TEMPLATE
rm $TEMP_TEMPLATE


# Y creamos las imagenes...
for i in `ls Pelicula*mpg` ; do
vcdimager -t vcd2 -c $i.cue -b $i.bin $i
done

-- Final divx2vcd --


Divx2CVCD:

New script Divx2CVCD (16/12/2002). This scripts gets all information from the .avi file, and then calculates automatically the video bitrate to make it fit in a CD in CVCD format (VCD with variable bitrate). You can change the QUANTUM variable. It's the quality (like the CQ-Constant Quality from TMPGenc), it must be between 2 and 31, the smaller it is, the biggest quality. With a value under 8 you get good quality. You can change AUDIORATE too. The script is available here, and I'm pasting it here:
News(06/09/2003): New script divx2cvcd available. This new script doesn't use transcode anymore so now supports more codecs and its more customizable.

-- Inicio divx2cvcd --


#!/bin/bash

# Este script pasa un Divx a CVCD. Para los archivos temporales se
# necesita al menos 4.5 Gigas (m1v y mpa, los .mpg y los .bin)

DIR=`pwd`
TEMPFOLDER=/tmp/divx2vcd-$RANDOM
TEMP_TEMPLATE=/tmp/tcmplex-template-$RANDOM

# CDSIZE Values. VCDs are write in Mode 2, so the filesizes are the
# the following:
# 74 Min/650Mb ---> CDSIZE=735
# 80 Min/700Mb ---> CDSIZE=795
CDSIZE=795
QUANTUM=5
# Maxrate ahora es automatico
#MAXRATE=900
AUDIORATE=128

if [ $# -eq 0 ]; then
echo "Usage:"
echo " divx2cvcd <divxfile>"
exit 1
fi

FILE=$1
if [ "$1" == "`basename \"$1\"`" ]; then
FILE="$DIR/$1"
fi

mkdir $TEMPFOLDER
cd $TEMPFOLDER

tcprobe -i "$FILE" > $TEMPFOLDER/info

WIDTH=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /width=(\d+)/ ; print $1' `
HEIGHT=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /height=(\d+)/ ; print $1' `
FPS=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /V: (.+?) fps/ ; print $1' `
FPS_1=`echo "scale=1 ; $FPS/1"| bc -l`
FRAMES=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /frames=(\d+)/ ; print $1' `
SEGUNDOS_TOTAL=`echo "scale=0 ; ($FRAMES / $FPS)"| bc -l`
HORAS=`echo "scale=0 ; ($SEGUNDOS_TOTAL / 3600)"| bc -l`
MINUTOS=`echo "scale=0 ; (($SEGUNDOS_TOTAL - \
3600 * $HORAS)/60)"| bc -l`
SEGUNDOS=`echo "scale=0 ; ($SEGUNDOS_TOTAL % 60)"| bc -l`

VIDEO_RATE=`echo "scale=0 ;(($CDSIZE * 1024 - \
($AUDIORATE/8*$SEGUNDOS_TOTAL))*8 / $SEGUNDOS_TOTAL)"| bc -l`
# +5%
MAXRATE=`echo "scale=0 ; ($VIDEO_RATE * 105 / 100)" | bc -l`

echo "*************** FILE INFO ***************"
echo "Frame Size: ${WIDTH}x${HEIGHT} - FPS: $FPS"
echo "Length: $FRAMES - Seconds: $SEGUNDOS_TOTAL"
echo "$HORAS hours, $MINUTOS minutes, $SEGUNDOS seconds"
echo "Recommended averagge video bitrate: $VIDEO_RATE"
echo "Using max video bitrate: $MAXRATE"


if [ $FPS_1 == "29.9" -o $FPS_1 == "30" -o $FPS_1 == "23.9" ]; then
WIDTH_OUT=352
HEIGHT_OUT=240
else
WIDTH_OUT=352
HEIGHT_OUT=288
fi

echo "Video Output: ${WIDTH_OUT}x${HEIGHT_OUT}"

# Ahora calculamos los valores pa los bordes.

ANCHO_1_1_OUT=`echo "($HEIGHT_OUT * 4/3)"| bc -l`
ALTO_OUT=`echo "$HEIGHT / ($WIDTH / $ANCHO_1_1_OUT)" | bc -l`
# Redondeamos
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT/1"| bc -l`
# Nos aseguramos de que sea par
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT+$ALTO_OUT%2" | bc -l`

BORDE=`echo "scale=0 ; ($HEIGHT_OUT-$ALTO_OUT)/2"| bc -l`

echo "alto sin bordes: $ALTO_OUT, con borde: $BORDE"

# Borramos Pelicula.m1v y Pelicula.mpa
rm -f Pelicula.m1v Pelicula.mpa


cd $TEMPFOLDER
echo "transcode -i \"$FILE\" -V -x mplayer -y mpeg2enc,mp2enc \
-F 2,\"-q $QUANTUM\" -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula -w $MAXRATE"
transcode -i "$FILE" -V -x mplayer -y mpeg2enc,mp2enc \
-F 2,"-q $QUANTUM" -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula -w $MAXRATE

rm $TEMPFOLDER/*
rmdir $TEMPFOLDER

cd $DIR


# Si no hay Pelicula.m1v y Pelicula.mpa salir
[ -f Pelicula.m1v -a -f Pelicula.mpa ] || exit 1

rm -f Pelicula*.mpg

#Ahora multiplexamos el mpg
echo "maxFileSize = $CDSIZE" > $TEMP_TEMPLATE
tcmplex -i Pelicula.m1v -p Pelicula.mpa -o Pelicula.mpg \
-m 1 -F $TEMP_TEMPLATE
rm $TEMP_TEMPLATE


# Y creamos las imagenes...
for i in `ls Pelicula*.mpg` ; do
vcdimager -t vcd2 -c $i.cue -b $i.bin $i
done

-- Final divx2cvcd --



Divx2SVCD:

For the SVCD creation is basically the same script, I only adjusted it to create a SVCD. You can change CDSIZE, QUANTUM, MAXVIDEORATE and AUDIORATE. You don't need to create an bbmpeg template because it creates it automatically.. Like before, you can download the script from here, and I paste it here also:

-- Inicio divx2svcd --

#!/bin/bash

# Este script pasa un Divx a SVCD. Para los archivos temporales se
# necesita al menos 4.5 Gigas (m2v y mpa, los .mpg y los .bin)

DIR=`pwd`
TEMPFOLDER=/tmp/divx2svcd-$RANDOM
TEMPLATE=$TEMPFOLDER/template

# CDSIZE Values. VCDs are write in Mode 2, so the filesizes are the
# the following:
# 74 Min/650Mb ---> CDSIZE=735
# 80 Min/700Mb ---> CDSIZE=795
CDSIZE=795
QUANTUM=7
MAXVIDEORATE=4000000
AUDIORATE=160

if [ $# -eq 0 ]; then
echo "Usage:"
echo " divx2svcd <divxfile>"
exit 1
fi


FILE=$1
if [ "$1" == "`basename \"$1\"`" ]; then
FILE="$DIR/$1"
fi


mkdir $TEMPFOLDER
cd $TEMPFOLDER

# Create a template for bbmpeg encoder
echo "quant_value = $QUANTUM" > $TEMPLATE
echo "max_bitrate = $MAXVIDEORATE" >> $TEMPLATE

echo "Dir: $DIR"
echo "Temp: $TEMPFOLDER"
tcprobe -i "$FILE" > $TEMPFOLDER/info

WIDTH=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /width=(\d+)/ ; print $1' `
HEIGHT=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /height=(\d+)/ ; print $1' `
FPS=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /V: (.+?) fps/ ; print $1' `
FPS=`echo "scale=1 ; $FPS/1"| bc -l`
FRAMES=`grep '\[avilib\] V:' $TEMPFOLDER/info | \
perl -e ' $line=<STDIN> ; $line =~ /frames=(\d+)/ ; print $1' `
SEGUNDOS_TOTAL=`echo "scale=0 ; ($FRAMES / $FPS)"| bc -l`
HORAS=`echo "scale=0 ; ($SEGUNDOS_TOTAL / 3600)"| bc -l`
MINUTOS=`echo "scale=0 ; (($SEGUNDOS_TOTAL - 3600 * $HORAS)/60)"| \
bc -l`
SEGUNDOS=`echo "scale=0 ; ($SEGUNDOS_TOTAL % 60)"| bc -l`

echo "*************** FILE INFO ***************"
echo "Frame Size: ${WIDTH}x${HEIGHT} - FPS: $FPS"
echo "Length: $FRAMES - Seconds: $SEGUNDOS_TOTAL"
echo "$HORAS hours, $MINUTOS minutes, $SEGUNDOS seconds"

if [ $FPS == "29.9" -o $FPS == "30" -o $FPS == "23.9" ]; then
WIDTH_OUT=480
HEIGHT_OUT=480
MPEG_OPTIONS=s,2,$TEMPLATE
else
WIDTH_OUT=480
HEIGHT_OUT=576
MPEG_OPTIONS=s,3,$TEMPLATE
fi

echo "Salida: $WIDTH_OUT x $HEIGHT_OUT"

# Ahora calculamos los valores pa los bordes.

ANCHO_1_1_OUT=`echo "($HEIGHT_OUT * 4/3)"| bc -l`
ALTO_OUT=`echo "$HEIGHT / ($WIDTH / $ANCHO_1_1_OUT)" | bc -l`
# Redondeamos
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT/1"| bc -l`
# Nos aseguramos de que sea par
ALTO_OUT=`echo "scale=0 ; $ALTO_OUT+$ALTO_OUT%2" | bc -l`

BORDE=`echo "scale=0 ; ($HEIGHT_OUT-$ALTO_OUT)/2"| bc -l`
echo "alto sin bordes: $ALTO_OUT, con borde: $BORDE"

# Borramos Pelicula.m1v y Pelicula.mpa
rm -f Pelicula.m2v Pelicula.mpa


cd $TEMPFOLDER
echo "transcode -i \"$FILE\" -V -x mplayer -y mpeg \
-F $MPEG_OPTIONS -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula"
transcode -i "$FILE" -V -x mplayer -y mpeg \
-F $MPEG_OPTIONS -Z ${WIDTH_OUT}x$ALTO_OUT -Y -$BORDE,0,-$BORDE,0 \
--export_asr 2 -E 44100 -b $AUDIORATE -o $DIR/Pelicula

cd $DIR

[ -f Pelicula.m2v -a -f Pelicula.mpa ] || exit 1

rm -f Pelicula*.mpg

# Plantilla pa multiplexar
echo "maxFileSize = $CDSIZE" >> $TEMPLATE

#Ahora multiplexamos el .mpg
tcmplex -i Pelicula.m2v -p Pelicula.mpa -o Pelicula.mpg \
-m s -F $TEMPLATE

rm $TEMPFOLDER/*
rmdir $TEMPFOLDER

# Y creamos las imagenes...
for i in `ls Pelicula*mpg` ; do
vcdimager -t svcd -c $i.cue -b $i.bin $i
done

-- Final divx2svcd --

Subtitles:

If we've got a divx file in a foreign language, and a subtitles file it is also possible to transcode them when we create the *VCD. The subtitles will be recorded as part of the movie (so you can't disable them when watching the *VCD).

The method is quite simple, you just have to have a subtitles file supported by mplayer (subrip, microdvd... mplayer supports almost everything), and put the file in the same folder as the .avi, and rename the file so it has exactly the same name as the .avi file
(except the extension of course). This way we make mplayer to autoload the subtitles. You can try if it works before transcoding, just do mplayer <file.avi> and see if the subtitles are autoloaded.

Well, I hope this little guide was helpful for you ;).


BerliOS Logo










Guides (english)
Ripping DVDs to Divx with mencoder
Transcoding Divx to VCD, SVCD, CVCD, etc.
Divx and DVD to VCD with mencvcd

Guías (español)
Ripeando DVSs a Divx con mencoder
Pasando Divx a VCD, SVCD, CVCD, etc.
Divx y DVD a VCD con mencvcd

Forums (english)
Divx
VCD, SVCD, CVCD

Forums (spanish)
Divx
VCD, SVCD, CVCD

Links
Encoding Divx en Linux (Traducción de La Guía de Moritz Bunkus)

IT Services UK