#!/bin/bash
# ---------------------------------------------------------------------------- #
## \file makedivx.sh
## \author Sebastien Beaugrand
## \sa http://beaugrand.chez.com/
## \copyright CeCILL 2.1 Free Software license
# ---------------------------------------------------------------------------- #
# This is an interactive shell script to rip DVD and encode DIVX.
# It can :
# - rip, encode audio, encode video, separately into different sessions
# - crop the black bars with autodetection
# - choose the best resolution for the 16:9 or 4:3 format
# - maximize volume (with a mencoder patch)
# - extract subtitle into a separated text file (with transcode tools)
# - split the AVI
# The video bitrate is a bit different from the mencoder recommendation, it's
# for a maximum filling for one CD, or to leave a margin to split the AVI.
# Type makedivx.sh --help for options.
# ---------------------------------------------------------------------------- #
# Date Author Comments
# ---------------------------------------------------------------------------- #
# 25/02/2003 Sebastien Beaugrand Creation
# 20/04/2004 Sebastien Beaugrand Add crop autodetection process
# 30/07/2004 Sebastien Beaugrand Add volume maximization and AVI spliting
# 17/08/2004 Sebastien Beaugrand Add volume maximization with normalize
# 21/09/2004 Sebastien Beaugrand Add automatic title with lsdvd
# 24/09/2006 Sebastien Beaugrand Encode audio and video at the same time to
# avoid desynchronization
# ---------------------------------------------------------------------------- #
# Gray format : ffmpeg -i 01.avi -vf format=gray -pix_fmt yuv420p 01.mp4
# Limits the CPU usage : cpulimit -e mencoder -l 50
# ---------------------------------------------------------------------------- #
gnu=true
lang=fr
ratemin=800
marginbr=6
splitmarginsize=30
tcpath=~/tmp/transcode
#mpeg4opt=vhq:v4mv:trell:vqmin=2:vlelim=-4:vcelim=9:lumi_mask=0.05:dark_mask=0.01
mpeg4opt=vhq:v4mv:trell:vqmin=2:o=luma_elim_threshold=-4
mpeg4opt=$mpeg4opt:o=chroma_elim_threshold=9:lumi_mask=0.05:dark_mask=0.01
red="\033[31;1m"
green="\033[32;1m"
blue="\033[34;1m"
reset="\033[0m"
# ---------------------------------------------------------------------------- #
# Print a fatal error
# ---------------------------------------------------------------------------- #
fatal()
{
echo -e "$blue$1\npress enter to quit$reset"
read
exit -1
}
# ---------------------------------------------------------------------------- #
# Read from standard input
# ---------------------------------------------------------------------------- #
myRead()
{
echo -ne "$green$1 [$2] $reset"
if [ $auto = no ]; then
read ret
if [ -z "$ret" ]; then
ret=$2
fi
else
echo
ret=$2
fi
}
# ---------------------------------------------------------------------------- #
# Read lsdvd
# ---------------------------------------------------------------------------- #
readLsdvd()
{
if [ ! -r lsdvd.txt ]; then
if type lsdvd &>/dev/null ; then
lsdvd -q $dev | grep a >lsdvd.txt
else
echo -e "$blue"
echo "for automatic value of the title install lsdvd"
echo -e "$reset"
fi
fi
}
# ---------------------------------------------------------------------------- #
# Select title
# ---------------------------------------------------------------------------- #
selectTitle()
{
if [ -z "$title" ]; then
title=1
readLsdvd
if [ -r lsdvd.txt ]; then
cat lsdvd.txt
title=`tail -n 1 lsdvd.txt`
title=`echo ${title:0-2:2} | awk '{ print $0+0 }'`
fi
if [ $title = 0 ]; then
echo -e "${blue}lsdvd error$reset"
title=1
fi
myRead "title ?" $title
checkNumericValue $ret "title" 1
title=dvd://$ret
if [ -n "$dev" ]; then
title="-dvd-device $dev $title"
fi
fi
}
# ---------------------------------------------------------------------------- #
# Read the DVD structure
# ---------------------------------------------------------------------------- #
readStructure()
{
if [ ! -r structure.txt ]; then
selectTitle
mplayer $title -v -nosound -novideo >structure.txt 2>/dev/null
fi
}
# ---------------------------------------------------------------------------- #
# Select title and angle
# ---------------------------------------------------------------------------- #
selectTitleAndAngle()
{
selectTitle
readStructure
if [ -z "$angle" ]; then
n=`grep "angles" structure.txt`
n=${n:10:1}
if ((n > 1)); then
myRead "angle ?" 1
checkNumericValue $ret "angle" 1
angle="-dvdangle $ret"
fi
fi
}
# ---------------------------------------------------------------------------- #
# Select chapters
# ---------------------------------------------------------------------------- #
selectChapters()
{
if [ -z "$first" ] || [ -z "$last" ]; then
selectTitle
readLsdvd
myRead "first chapter ?" 1
first=$ret
last=`echo $title | awk 'BEGIN { FS="//" } { print $2 }'`
last=`head -n $last lsdvd.txt | tail -n 1 | cut -d ' ' -f 6 |\
tr -d ',\n' | awk '{ print $0+0 }'`
myRead "last chapter ?" $last
last=$ret
fi
}
# ---------------------------------------------------------------------------- #
# Rip the DVD
# ---------------------------------------------------------------------------- #
makeDump()
{
list=
if [ -f dump.01 ]; then
myRead "do you want to delete dump files ? (y/n)" "n"
if [ $ret = y ]; then
rm -f dump.*
fi
fi
selectTitleAndAngle
selectChapters
for ((i = first; i <= last; ++i)); do
file=dump.`printf %02d $i`
list="$list $file"
if [ -f $file ]; then
myRead "do you want to overwrite $file ? (y/n)" "n"
if [ $ret = n ]; then
continue
fi
fi
echo -e "${blue}writing $file$reset"
# With mencoder it doesn't work well, then we use mplayer to dump.
# On some DVD the volume can be different when we select a chapter,
# in this case it's better to encode directly from the DVD (this
# problem was encountered only once on "Rammstein Live Aus Berlin").
mplayer $title $angle -chapter $i-$i -dumpstream -dumpfile $file
done
}
# ---------------------------------------------------------------------------- #
# Select input
# ---------------------------------------------------------------------------- #
selectInput()
{
if [ $direct = y ]; then
selectTitleAndAngle
elif [ -z "$list" ]; then
list=
if [ -z "$first" ] || [ -z "$last" ]; then
myRead "first chapter ?" 1
first=$ret
last=`ls -1 --indicator-style=none dump.* 2>/dev/null | tail -n 1`
if [ -n "$last" ]; then
last=`echo ${last:0-2:2} | awk '{ print $0+0 }'`
else
fatal "cannot access to any dump file"
fi
myRead "last chapter ?" $last
last=$ret
fi
for ((i = first; i <= last; ++i)); do
file=dump.`printf %02d $i`
if [ ! -r $file ]; then
fatal "cannot access to $file"
fi
list="$list $file"
done
echo -e "${blue}using the files : $reset"
echo -e $list
fi
}
# ---------------------------------------------------------------------------- #
# Maximize volume
# ---------------------------------------------------------------------------- #
maximizeVolume()
{
if [ $volume != 1 ]; then
return
fi
myRead "maximize volume ? (y/n)" y
if [ $ret = y ]; then
if [ $normalize = "true" ]; then
if [ $direct = y ]; then
mplayer $title $angle -vo null\
-ao pcm:file=sound.wav -alang $lang
volume=`normalize -n -a 1 --fractions sound.wav`
echo $volume
volume=`echo $volume | awk 'BEGIN { FS = " " } { print 1/$2 }'`
else
myRead "only one temporary sound file ? (y/n)" y
if [ $ret = y ]; then
if [ -f sound.wav ]; then
myRead "do you want to overwrite sound.wav ? (y/n)" "n"
if [ $ret = y ]; then
cat $list |\
mplayer -vo null -ao pcm:file=sound.wav -aid $aid -
fi
else
cat $list |\
mplayer -vo null -ao pcm:file=sound.wav -aid $aid -
fi
volume=`normalize -n -a 1 --fractions sound.wav`
echo $volume
volume=\
`echo $volume | awk 'BEGIN { FS = " " } { print 1/$2 }'`
else
list2=
for ((i = first; i <= last; ++i)); do
file1=dump.`printf %02d $i`
file2=sound`printf %02d $i`.wav
list2="$list2 $file2"
if [ -f $file2 ]; then
myRead "do you want to overwrite $file2 ? (y/n)" "n"
if [ $ret = n ]; then
continue
fi
fi
echo -e "${blue}writing $file2$reset"
mplayer $file1 -vo null -ao pcm:file=$file2 -aid $aid
done
normalize -n -a 1 --fractions -- $list2 |\
grep "sound" >normalize.txt
cat normalize.txt
volume=`awk '\
BEGIN { FS = " "; m = 0 }\
{ v = strtonum($2); if (v > m) m = v }\
END { if (m > 0) print 1/m; else print 1 }' normalize.txt`
fi
fi
else
if [ ! -r volume.txt ]; then
echo -e "${blue}warning: mencoder must be patched for this"
echo -e "see http://beaugrand.chez.com/"
echo -e "or use normalize with -n option"
echo -e "please wait, it takes a few minutes...$reset"
if [ $direct = y ]; then
mencoder $title $angle -ovc frameno -o /dev/null -oac pcm\
-alang $lang -quiet $mencOpt 2>/dev/null |\
grep "gain=" >volume.txt
else
echo\
mencoder -ovc frameno -o /dev/null -oac pcm\
-aid $aid -quiet $mencOpt $list
mencoder -ovc frameno -o /dev/null -oac pcm\
-aid $aid -quiet $mencOpt $list 2>/dev/null |\
grep "gain=" >volume.txt
fi
fi
tail -n 1 volume.txt
volume=`tail -n 1 volume.txt | cut -d "=" -f 3`
if [ -z "$volume" ]; then
echo -e "${blue}it seems mencoder is not patched for this"
echo -e "please see http://beaugrand.chez.com/"
echo -e "or use normalize with -n option$reset"
volume=1
fi
fi
echo -ne $bel
myRead "volume ?" $volume
volume=$ret
fi
}
# ---------------------------------------------------------------------------- #
# Select the subtitle
# ---------------------------------------------------------------------------- #
selectSubtitleId()
{
readStructure
sid=`grep "sid" structure.txt | grep $lang | tail -n 1`
sid=${sid:18:2}
if [ -z "$sid" ]; then
sid=`grep -m 1 "sid" structure.txt`
sid=${sid:18:2}
if [ -z "$sid" ]; then
echo -e "${blue}no subtitle found$reset"
return
fi
fi
myRead "sid ?" $sid
sid="-sid $ret"
}
# ---------------------------------------------------------------------------- #
# Select scale
# ---------------------------------------------------------------------------- #
selectScale()
{
if [ -z "$res" ]; then
# Dimensions are adapted to the majority of the resolutions used
if [ $aspect = '1' ]; then
myRead "resolution :\
\n (1) 720:400\n (2) 640:352\n (3) 576:320\n (4) 512:288\n" "1"
case $ret in
1) res=720:400 ;; # 720x405
2) res=640:352 ;; # 640x360
3) res=576:320 ;; # 576x324
4) res=512:288 ;;
esac
elif [ $aspect = '2' ]; then
myRead "resolution :\
\n (1) 720:528\n (2) 640:480\n (3) 576:432\n (4) 512:384\n" "2"
case $ret in
1) res=720:528 ;; # 720x540
2) res=640:480 ;;
3) res=576:432 ;;
4) res=512:384 ;;
esac
fi
fi
# The 4:3 videos are often interlaced
if [ $aspect != '1' ] && [ -z "$deinterlace" ]; then
myRead "deinterlace ? (y/n)" "n"
if [ $ret = y ]; then
deinterlace="yadif=0,"
fi
fi
if [ -n "$res" ]; then
if [ -n "$crop" ]; then
resx=`echo $res | cut -d ':' -f 1`
resy=`echo $res | cut -d ':' -f 2`
width=`echo $crop | cut -d ':' -f 1`
height=`echo $crop | cut -d ':' -f 2`
((resy = resy * 720 * height / 576 / width))
if ((resy / 16 * 16 != resy)); then
((resy = (resy / 16 + 1) * 16))
fi
res=$resx:$resy
fi
scale="scale=$res"
echo -e "$blue$scale$reset"
fi
}
# ---------------------------------------------------------------------------- #
# Select crop and scale
# ---------------------------------------------------------------------------- #
selectCropAndScale()
{
aspect=3
if [ -z "$res" ]; then
myRead "aspect :\n (1) 16:9\n (2) 4:3\n (3) no scale\n" 1
aspect=$ret
fi
if [ -z "$crop" ]; then
if [ $aspect = '1' ]; then
echo "try mplayer -vf rectangle=720:432:0:72"
myRead "crop ? (y/n/rectangle)" "720:432:0:72"
else
myRead "crop ? (y/n/rectangle)" "n"
fi
if [ $ret = n ]; then
selectScale
return
elif [ $ret != y ]; then
echo "crop=$ret" >>crop.txt
fi
if [ ! -r crop.txt ]; then
myRead "cropdetect ? (y/n)" "y"
if [ $ret = y ]; then
detect="-quiet -nosound -vo null -speed 100 -vf cropdetect=24:1"
detect="$detect -nocache -nozoom -nolirc"
echo
if [ $direct = y ]; then
if [ $gnu = "true" ]; then
mplayer $title $angle $detect 2>/dev/null |\
grep "CROP" | tee crop.txt |\
sed -n '99~100s/^.*$/\o033[2A/p;100~100='
else
mplayer $title $angle $detect 2>/dev/null |\
grep "CROP" >crop.txt
fi
else
if [ $gnu = "true" ]; then
cat $list | mplayer $detect - 2>/dev/null |\
grep "CROP" | tee crop.txt |\
sed -n '99~100s/^.*$/\o033[2A/p;100~100='
else
cat $list | mplayer $detect - 2>/dev/null |\
grep "CROP" >crop.txt
fi
fi
fi
fi
if [ -r crop.txt ]; then
crop=`tail -n 1 crop.txt | cut -d '=' -f 2 | cut -d ')' -f 1`
else
crop=720:576:0:0
fi
echo -ne $bel
myRead "crop ?" $crop
crop=$ret
fi
# Scale
selectScale
if [ "$crop" = "720:576:0:0" ]; then
crop=
else
echo -e "${blue}crop=$crop$reset"
crop="crop=$crop,"
fi
}
# ---------------------------------------------------------------------------- #
# Select rate
# ---------------------------------------------------------------------------- #
selectRate()
{
# With 800kbps we can encode a 1h45 DVD on a 700MB CD
selectTitle
readLsdvd
time=`echo $title | awk 'BEGIN { FS="//" } { print $2 }'`
time=`head -n $time lsdvd.txt | tail -n 1 | cut -c 20-27`
hour=`echo ${time:0:2} | awk '{ print $0+0 }'`
min=`echo ${time:3:2} | awk '{ print $0+0 }'`
sec=`echo ${time:6:2} | awk '{ print $0+0 }'`
((time = hour * 3600 + min * 60 + sec))
((rate1 = (cdrsize - 5) * 1024 * 1024 / 125 / time - audiobr - marginbr))
((rate2 = ((cdrsize - 5) * 2 - splitmarginsize) *\
1024 * 1024 / 125 / time - audiobr))
echo -ne "${blue}try $rate1 for ${cdrsize}MB CD,"
echo -e " $rate2 for 2 x ${cdrsize}MB CD$reset"
if ((rate2 > 900)); then
rate2=900
fi
if [ -z "$nbcd" ]; then
if ((rate1 >= ratemin)); then
myRead "video bitrate ?" $rate1
else
myRead "video bitrate ?" $rate2
fi
else
if [ $nbcd = '1' ]; then
myRead "video bitrate ?" $rate1
else
myRead "video bitrate ?" $rate2
fi
fi
rate=$ret
}
# ---------------------------------------------------------------------------- #
# Select audio
# ---------------------------------------------------------------------------- #
selectAudio()
{
if [ $direct = y ]; then
return
fi
echo -ne "${blue}audio channel"
echo -e " to be check with mplayer dump.* -aid <id> :$reset"
aid=0
if [ -r structure.txt ]; then
grep "aid" structure.txt
aid=`grep "aid" structure.txt | grep -m 1 $lang`
aid=${aid:0-4:3}
if [ -z "$aid" ]; then
aid=`grep -m 1 "aid" structure.txt`
aid=${aid:0-4:3}
fi
# Case for the zero value
aid=`echo "$aid" | cut -d " " -f 2`
fi
myRead "audio channel ?" $aid
aid=$ret
}
# ---------------------------------------------------------------------------- #
# Encode the video
# ---------------------------------------------------------------------------- #
makeVideo()
{
myRead "pass :\n (1) 1\n (2) 2\n (3) 1&2\n" 3
pass=$ret
selectInput
if [ -z "$name" ]; then
name=`ls -1 --indicator-style=none *.avi 2>/dev/null |\
grep -v frameno -m 1`
if [ $pass != '2' ] || ([ $pass = '2' ] && [ -z "$name" ]); then
name=video
echo -e "${blue}current directory :$reset"
ls
fi
myRead "enter a name" $name
name=$ret
fi
ext=${name##*.}
if [ "$ext" != avi ]; then
name=${name}.avi
fi
if ((pass & 1)); then
if [ -f $name ]; then
fatal "$name is already exist !"
fi
else
if [ ! -f divx2pass.log ]; then
fatal "divx2pass.log do not exist !"
fi
fi
if [ -z "$rate" ]; then
selectRate
fi
# Crop and scale
selectCropAndScale
if [ -n "$deinterlace" ] || [ -n "$crop" ] || [ -n "$res" ]; then
filters="-vf $deinterlace$crop$scale"
fi
# Additionnal subtitle
if [ -z "$sid" ]; then
grep "sid" structure.txt
myRead "additionnal subtitle ? (y/n)" "n"
if [ $ret = y ]; then
selectSubtitleId
if [ -z "$sid" ]; then
myRead "continue ? (y/n)" "y"
if [ $ret = n ]; then
exit 0
fi
sid="-nosub"
fi
else
sid="-nosub"
fi
fi
# Audio
selectAudio
# Volume
maximizeVolume
# Encode
if [ $direct = y ]; then
if ((pass & 1)); then
mencoder $title $angle $filters $sid\
-ovc lavc -lavcopts vcodec=mpeg4:vpass=1:vbitrate=$rate:$mpeg4opt\
-oac mp3lame -lameopts cbr:br=$audiobr:vol=$volume:aq=9\
-alang $lang -ffourcc DIVX -o $name $mencOpt
fi
if ((pass & 2)); then
info="$title $angle $filters $sid vbitrate=$rate:$mpeg4opt"
info="$info cbr:br=$audiobr:vol=$volume:aq=0 $mencOpt -alang $lang"
info="%"`expr length "$info"`"%$info"
mencoder $title $angle $filters $sid\
-ovc lavc -lavcopts vcodec=mpeg4:vpass=2:vbitrate=$rate:$mpeg4opt\
-oac mp3lame -lameopts cbr:br=$audiobr:vol=$volume:aq=0\
-alang $lang -ffourcc DIVX -o $name -info comment="$info" $mencOpt
fi
else
if ((pass & 1)); then
set -x
mencoder $filters $sid\
-ovc lavc -lavcopts vcodec=mpeg4:vpass=1:vbitrate=$rate:$mpeg4opt\
-oac mp3lame -lameopts cbr:br=$audiobr:vol=$volume:aq=9 -aid $aid\
-ffourcc DIVX -o $name $mencOpt $list
{ set +x; } 2>/dev/null
fi
if ((pass & 2)); then
info="$filters $sid vbitrate=$rate:$mpeg4opt"
info="$info cbr:br=$audiobr:vol=$volume:aq=0 $mencOpt -aid $aid"
info="%"`expr length "$info"`"%$info"
set -x
mencoder $filters $sid\
-ovc lavc -lavcopts vcodec=mpeg4:vpass=2:vbitrate=$rate:$mpeg4opt\
-oac mp3lame -lameopts cbr:br=$audiobr:vol=$volume:aq=0 -aid $aid\
-ffourcc DIVX -o $name -info comment="$info" $mencOpt $list
{ set +x; } 2>/dev/null
fi
fi
}
# ---------------------------------------------------------------------------- #
# Extract subtitle
# ---------------------------------------------------------------------------- #
extractSubtitle()
{
# It needs transcode tools :
# tcextract, subtitle2pgm, pgm2txt, srttool
if [ $direct = y ]; then
fatal "sorry, you must rip the DVD"
fi
selectInput
grep "sid" structure.txt
selectSubtitleId
if [ -z "$sid" ]; then
fatal
fi
echo -e "${blue}please wait...$reset"
sid=0x2$ret
cat $list | ${tcpath}/import/tcextract -x ps1 -t vob -a $sid >subs
echo -ne $bel
myRead "language ?" "francais"
lang=$ret
${tcpath}/contrib/subrip/subtitle2pgm -o $lang -c $subgreylevels < subs
${tcpath}/contrib/subrip/pgm2txt $lang
myRead "check spelling ? (y/n)" "n"
if [ $ret = y ]; then
ispell -d $lang $lang*txt
fi
${tcpath}/contrib/subrip/srttool -s -w < $lang.srtx >$lang.srt
}
# ---------------------------------------------------------------------------- #
# Extract wav
# ---------------------------------------------------------------------------- #
extractWav()
{
selectInput
myRead "number of files :\n (1) one per chapter\n (2) only one\n" "1"
if [ $ret = 1 ]; then
if [ $direct = y ]; then
selectChapters
else
selectAudio
fi
for ((i = first; i <= last; ++i)); do
n=`printf %02d $i`
if [ $direct = y ]; then
mplayer $title $angle -chapter $i-$i\
-vo null -ao pcm:file=audio_$n.wav
else
mplayer dump.$n -vo null -aid $aid -ao pcm:file=audio_$n.wav
fi
done
else
if [ $direct = y ]; then
mplayer $title $angle -vo null -ao pcm:file=audio.wav
else
selectAudio
cat $list | mplayer -vo null -aid $aid -ao pcm:file=audio.wav -
fi
fi
}
# ---------------------------------------------------------------------------- #
# Check a numeric value
# ---------------------------------------------------------------------------- #
checkNumericValue()
{
if [ -n "`echo $1 | grep [^0-9,]`" ] ||\
([ -n "$3" ] && (($1 < $3))) ||\
([ -n "$4" ] && (($1 > $4))); then
fatal "bad value for: $2"
fi
}
# ---------------------------------------------------------------------------- #
# Read options
# ---------------------------------------------------------------------------- #
readOptions()
{
# Initialize some variables set by options.
dir=
auto=no
sid=
subgreylevels=255,255,0,255
title=
angle=
first=
last=
normalize=false
nbcd=
crop=
subtitle=no
split=no
ipod=no
res=
rate=
audiobr=128
volume=1
wav=no
deinterlace=
dev=
cdrsize=700
verbose=no
bel="\a"
mencOpt=
ac_prev=
for ac_option
do
# If the previous option needs an argument, assign it.
if [ -n "$ac_prev" ]; then
case "$ac_prev" in
rate)
checkNumericValue $ac_option "$ac_prev" 4 24000000 ;;
audiobr)
checkNumericValue $ac_option "$ac_prev" 32 320 ;;
title | angle | first)
checkNumericValue $ac_option "$ac_prev" 1 ;;
nbcd)
checkNumericValue $ac_option "$ac_prev" 1 2 ;;
cdrsize)
checkNumericValue $ac_option "$ac_prev" 0 2048 ;;
esac
if [ "$ac_prev" != "--" ]; then
eval "$ac_prev=\$ac_option"
ac_prev=
else
mencOpt="$mencOpt $ac_option"
fi
continue
fi
case "$ac_option" in
-d | -dir | --dir)
ac_prev=dir ;;
-d=* | -dir=* | --dir=*)
dir=`echo $ac_option | cut -d '=' -f 2` ;;
-A | -auto | --auto)
auto=yes
bel=
;;
-f | -sid | --sid)
ac_prev=sid ;;
-f=* | -sid=* | --sid=*)
sid=`echo $ac_option | cut -d '=' -f 2` ;;
-g | -subgreylevels | --subgreylevels)
ac_prev=subgreylevels ;;
-g=* | -subgreylevels=* | --subgreylevels=*)
subgreylevels=`echo $ac_option | cut -d '=' -f 2` ;;
-l | -crop | --crop)
ac_prev=crop ;;
-l=* | -crop=* | --crop=*)
crop=`echo $ac_option | cut -d '=' -f 2` ;;
-T | -chapter | --chapter)
ac_prev=first ;;
-T=* | -chapter=* | --chapter=*)
first=`echo $ac_option | cut -d '=' -f 2`
last=$first
checkNumericValue $first "chapter" 1
;;
-t | -title | --title)
ac_prev=title ;;
-t=* | -title=* | --title=*)
title=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $title "titre" 1
;;
-a | -angle | --angle)
ac_prev=angle ;;
-a=* | -angle=* | --angle=*)
angle=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $angle "angle" 1
;;
-n | -normalize | --normalize)
normalize=true ;;
-N | -nbcd | --nbcd)
ac_prev=nbcd ;;
-N=* | -nbcd=* | --nbcd=*)
angle=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $nbcd "nbcd" 1 2
;;
-D | -deinterlace | --deinterlace)
deinterlace="yadif=0," ;;
-s | -subtitle | --subtitle)
subtitle=yes ;;
-S | -split | --split)
split=yes ;;
-p | -ipod | --ipod)
ipod=yes ;;
-r | -res | --res)
ac_prev=res ;;
-r=* | -res=* | --res=*)
res=`echo $ac_option | cut -d '=' -f 2`
;;
-B | -videobr | --videobr)
ac_prev=rate ;;
-B=* | -videobr=* | --videobr=*)
rate=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $rate "videobr" 4 24000000
;;
-b | -audiobr | --audiobr)
ac_prev=audiobr ;;
-b=* | -audiobr=* | --audiobr=*)
audiobr=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $audiobr "audiobr" 32 320
;;
-V | -vol | --vol)
ac_prev=volume ;;
-V=* | -vol=* | --vol=*)
volume=`echo $ac_option | cut -d '=' -f 2` ;;
-w | -wav | --wav)
wav=yes ;;
-i | -dev | --dev)
ac_prev=dev ;;
-i=* | -dev=* | --dev=*)
dev=`echo $ac_option | cut -d '=' -f 2` ;;
-c | -nocolors | --nocolors)
red=
green=
blue=
reset=
;;
-C | -cdrsize | --cdrsize)
ac_prev=cdrsize ;;
-C=* | -cdrsize=* | --cdrsize=*)
cdrsize=`echo $ac_option | cut -d '=' -f 2`
checkNumericValue $cdrsize "cdrsize" 0 2048
;;
-v | -verbose | --verbose)
verbose=yes ;;
-h | -help | --help)
this=${0##*/}
cat << EOF
$this is a shell script to rip DVD and encode to DIVX
It can :
- rip, encode audio, encode video, separately into different sessions
- crop the black bars with autodetection
- choose the best resolution for the 16:9 or 4:3 format
- maximize volume (with a mencoder patch)
- extract subtitle into a separated text file (with transcode tools)
- split the AVI
The video bitrate is a bit different from the mencoder recommendation, it's
for a maximum filling for one CD, or to leave a margin to split the AVI.
Usage: $this [options]
Options:
-A, --auto use automatic values
-a, --angle=N set angle
-B, --videobr=<4-24000000> set video bitrate
-b, --audiobr=<32-320> change audio bitrate for lame [$audiobr]
-C, --cdrsize=SIZE change the size of a CD [$cdrsize]
-c, --nocolors do not use colors
-D, --deinterlace use deinterlace filter
-d, --dir=DIR change directory [./]
-f, --sid=FILE|0-31 set subtitle file or sid
-g, --subgreylevels=LEVEL set subgrey levels [$subgreylevels]
-h, --help print this help message
-i, --dev=DEV change dvd device [/dev/dvd]
-l, --crop=CROP set crop (ex: 720:576:0:0 = no crop)
-N, --nbcd=<1-2> set number of CD
-n, --normalize use normalize to maximize volume
-p, --ipod make an ipod video
-r, --res=XXX:YYY set resolution
-S, --split split AVI
-s, --subtitle extract text subtitle
-T, --chapter=N set chapter
-t, --title=N set title
-V, --vol=<0-10> change audio input gain for lame [$volume]
-w, --wav extract audio to wav file(s)
-- options passed to mencoder (ex: -- -ni)
For more info type : vi $this
EOF
exit 0 ;;
--)
ac_prev=-- ;;
*)
fatal "unknown parameter: $ac_option" ;;
esac
done
if [ -n "$ac_prev" ] && [ "$ac_prev" != "--" ]; then
fatal "bad value for: $ac_prev"
fi
if [ -n "$sid" ]; then
if [ -f $sid ]; then
sid="-sub $sid -subfont-text-scale 3"
else
sid="-sid $sid"
fi
fi
if [ -n "$dir" ]; then
if [ ! -d $dir ]; then
myRead "$dir does not exist, create it ? (y/n)" y
if [ $ret = y ]; then
mkdir -p $dir
cd $dir
fi
else
cd $dir
fi
fi
if [ -n "$title" ]; then
title=dvd://$title
fi
if [ -n "$angle" ]; then
angle="-dvdangle $angle"
fi
if [ -n "$first" ]; then
last=$first
fi
}
# ---------------------------------------------------------------------------- #
# splitAVI
# ---------------------------------------------------------------------------- #
splitAVI()
{
if [ -f frameno.avi ]; then
mv frameno.avi frameno.avi.sav
fi
name=`ls -1 --indicator-style=none *.avi 2>/dev/null | tail -n 1`
myRead "avi to split ?" $name
name=$ret
n0=`mplayer "$name" -v -frames 0 2>/dev/null | grep "frames total" |\
awk '{ print $3 }'`
if [ -z "$n0" ]; then
myRead "frames total ?"
n0=$ret
fi
ret=n
while [ $ret = n ]; do
myRead "offset (secondes) ?" -60
offset=$ret
((time = n0 / 50 + offset))
echo $n0
echo -e "${blue}press return to start playing,"
echo -e "then press escape where to split$reset"
read ret
mplayer "$name" -vf framestep=I -ss $time -nofs -xy 1 2>/dev/null |\
grep "ct:" | tee keyframes.txt
frame=`tail -n 1 keyframes.txt | cut -d "/" -f 2 | cut -d " " -f 1`
myRead "frame=$frame (y/n)" y
done
name=`echo "$name" | sed 's/\.avi//'`
info=`mplayer -novideo -nosound -v $name.avi 2>/dev/null |\
grep "Comments :" | sed "s/Comments ://"`
info="%"`expr length "$info"`"%$info"
mencoder "$name.avi" -ovc copy -oac copy -frames $((frame - 1))\
-o "${name}_1.avi" -info comment="split $info" $mencOpt
time=`echo $frame | awk '{ print $0/25 }'`
mencoder "$name.avi" -ovc copy -oac copy -ss $time\
-o "${name}_2.avi" -info comment="split $info" $mencOpt
n1=`mplayer "${name}_1.avi" -v -frames 0 2>/dev/null |\
grep "frames total" | awk '{ print $3 }'`
n2=`mplayer "${name}_2.avi" -v -frames 0 2>/dev/null |\
grep "frames total" | awk '{ print $3 }'`
echo "${name}_1.avi: $n1 frames"
echo "${name}_2.avi: $n2 frames"
echo "$((n1 + n2))/$n0 frames"
}
# ---------------------------------------------------------------------------- #
# makeIpod
# ---------------------------------------------------------------------------- #
makeIpod()
{
if [ $direct = y ]; then
fatal "sorry, you must rip the DVD"
fi
selectInput
selectAudio
for ((i = first; i <= last; ++i)); do
num=`printf %02d $i`
file=dump.$num
mencoder $file -aid $aid -oac pcm -ovc copy -o dump.tmp $mencOpt
if [ -r titles.txt ]; then
title=`head -n $i titles.txt | tail -n 1`
title=" - $title"
fi
ffmpeg -f dvd -i dump.tmp -f mp4 -vcodec mpeg4 -maxrate 1000\
-b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec libfaac\
-ab 192 -s 320x180 -aspect 16:9 "$num$title.mov"
done
rm -f dump.tmp
}
# ---------------------------------------------------------------------------- #
# main
# ---------------------------------------------------------------------------- #
readOptions $*
if [ $split = yes ]; then
splitAVI
exit 0
fi
if [ -r structure.txt ]; then
echo -e "${blue}warning : structure.txt exist, it will be used$reset"
fi
dir=`pwd`
size=`df -Ph "$dir" | tail -n 1 | awk 'BEGIN { FS = " " } { print $4 }'`
echo -e "${blue}disk space left in $dir : $size$reset"
myRead "continue ? (y/n)" "y"
if [ $ret = n ]; then
exit 0
fi
if [ -f dump.01 ]; then
myRead "rip the DVD ? (y/n)" "n"
else
myRead "rip the DVD ? (y/n)" "y"
fi
if [ $ret = y ]; then
makeDump
direct=n
else
myRead "encode directly from the DVD ? (y/n)" "n"
direct=$ret
fi
if [ $subtitle = yes ]; then
extractSubtitle
exit 0
fi
if [ $wav = yes ]; then
extractWav
exit 0
fi
if [ $ipod = yes ]; then
makeIpod
exit 0
fi
myRead "encode video ? (y/n)" "y"
if [ $ret = y ]; then
makeVideo
fi
echo -ne "\a"